diff --git a/programs/frep/smiley b/programs/frep/smiley
index cda65eee53e3f8cea3ff042af099b66d749e896e..18df67ab3599488c5e63809f4c56a6e1faab5a0c 100644
--- a/programs/frep/smiley
+++ b/programs/frep/smiley
@@ -1 +1 @@
-{"modules":{"0.3625970106871924":{"definition":"//\n// frep circle\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep circle'\n//\n// initialization\n//\nvar init = function() {\n   mod.x.value = '0'\n   mod.y.value = '0'\n   mod.radius.value = '1'\n   }\n//\n// inputs\n//\nvar inputs = {\n   variables:{type:'',\n      event:function(evt){\n         for (var p in evt.detail)\n            mod[p].value = evt.detail[p]\n         outputs.variables.event()\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         var x = parseFloat(mod.x.value)\n         var y = parseFloat(mod.y.value)\n         var radius = parseFloat(mod.radius.value)\n         var fn = `((${radius})*(${radius})-((X-(${x}))*(X-(${x}))+(Y-(${y}))*(Y-(${y}))))`\n         var variables = ['X','Y']\n         var limits = [[x-radius,x+radius],[y-radius,y+radius]]\n         var type = 'Magnitude'\n         var shape = {function:fn,variables:variables,limits:limits,type:type}\n         mods.output(mod,'shape',shape)}\n         },\n   variables:{type:'',\n      event:function(){\n         var x = parseFloat(mod.x.value)\n         var y = parseFloat(mod.y.value)\n         var radius = parseFloat(mod.radius.value)\n         var vars = {x:x,y:y,radius:radius}\n         mods.output(mod,'variables',vars)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // x\n   //\n   div.appendChild(document.createTextNode('x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.x = input\n   //\n   // y\n   //\n   div.appendChild(document.createTextNode(' y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.y = input\n   div.appendChild(document.createElement('br'))\n   //\n   // r\n   //\n   div.appendChild(document.createTextNode('radius: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.radius = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.variables.event()\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"172","left":"279","inputs":{},"outputs":{}},"0.8373334092218472":{"definition":"//\n// frep view slice\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep view slice'\n//\n// initialization\n//\nvar init = function() {\n   mod.width.value = '1000'\n   mod.z.value = '0'\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'frep',\n      event:function(evt){\n         mod.fn.value = evt.detail.function\n         view_slice(evt.detail)\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   image:{type:'RGBA',\n      event:function(){\n         var ctx = mod.img.getContext(\"2d\")\n         var img = ctx.getImageData(0,0,mod.img.width,mod.img.height)\n         mods.output(mod,'image',img)\n         }}}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // on-screen drawing canvas\n   //\n   var canvas = document.createElement('canvas')\n      canvas.width = mods.ui.canvas\n      canvas.height = mods.ui.canvas\n      canvas.style.backgroundColor = 'rgb(255,255,255)'\n      div.appendChild(canvas)\n      mod.canvas = canvas\n   div.appendChild(document.createElement('br'))\n   //\n   // off-screen image canvas\n   //\n   var canvas = document.createElement('canvas')\n      mod.img = canvas\n   //\n   // x\n   //\n   div.appendChild(document.createTextNode('x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      input.addEventListener('input',function(){\n         mod.y.value = ''\n         mod.z.value = ''\n         })\n      div.appendChild(input)\n      mod.x = input\n   //\n   // y\n   //\n   div.appendChild(document.createTextNode(' y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      input.addEventListener('input',function(){\n         mod.x.value = ''\n         mod.z.value = ''\n         })\n      div.appendChild(input)\n      mod.y = input\n   //\n   // z\n   //\n   div.appendChild(document.createTextNode(' z: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      input.addEventListener('input',function(){\n         mod.x.value = ''\n         mod.y.value = ''\n         })\n      div.appendChild(input)\n      mod.z = input\n   div.appendChild(document.createElement('br'))\n   //\n   // width\n   //\n   div.appendChild(document.createTextNode('width: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      input.addEventListener('input',function(){\n         mod.height.value = ''\n         })\n      div.appendChild(input)\n      mod.width = input\n   //\n   // height\n   //\n   div.appendChild(document.createTextNode(' height: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      input.addEventListener('input',function(){\n         mod.width.value = ''\n         })\n      div.appendChild(input)\n      mod.height = input\n   div.appendChild(document.createElement('br'))\n   //\n   // function\n   //\n   div.appendChild(document.createTextNode('function: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn = input\n   div.appendChild(document.createElement('br'))\n   //\n   // view button\n   //\n   div.appendChild(document.createTextNode(' '))\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('view'))\n      btn.addEventListener('click',function(){\n         mod.win = window.open('')\n         mod.win.document.body.style.overflow = 'hidden'\n         mod.win.document.body.style.border = 0\n         mod.win.document.body.style.padding = 0\n         mod.win.document.body.style.margin = 0\n         mod.win.addEventListener('unload',function() {\n            mod.win = null\n            })\n         var canvas = document.createElement('canvas')\n            canvas.setAttribute('id',mod.div.id+'canvas')\n            mod.win.document.body.appendChild(canvas)\n         var ctx = canvas.getContext(\"2d\")\n         canvas.width = window.innerWidth\n         canvas.height = window.innerWidth\n         var h = mod.img.height\n         var w = mod.img.width\n         if (w > h) {\n            var wd = canvas.width\n            var hd = canvas.width*h/w\n            }\n         else {\n            var wd = canvas.height*w/h\n            var hd = canvas.height\n            }\n         ctx.fillStyle = '#dddddd'\n         ctx.fillRect(0,0,canvas.width,canvas.height)\n         ctx.drawImage(mod.img,0,0,wd,hd)\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n// view_slice\n//\nfunction view_slice(shape) {   \n   var fn = shape.function\n   var vars = shape.variables\n   var limits = shape.limits\n   var type = shape.type\n   var x = parseFloat(mod.x.value)\n   var y = parseFloat(mod.y.value)\n   var z = parseFloat(mod.z.value)\n   var w = parseInt(mod.width.value)\n   var h = parseInt(mod.height.value)\n   if (vars.length == 2) {\n      var xvar = vars[0]\n      var xlimits = limits[0]\n      var yvar = vars[1]\n      var ylimits = limits[1]\n      var zvar = ''\n      var zval = 0\n      }\n   else if (!isNaN(x)) {\n      var xvar = vars[1]\n      var xlimits = limits[1]\n      var yvar = vars[2]\n      var ylimits = limits[2]\n      var zvar = vars[0]\n      var zval = x\n      }\n   else if (!isNaN(y)) {\n      var xvar = vars[0]\n      var xlimits = limits[0]\n      var yvar = vars[2]\n      var ylimits = limits[2]\n      var zvar = vars[1]\n      var zval = y\n      }\n   else if (!isNaN(z)) {\n      var xvar = vars[0]\n      var xlimits = limits[0]\n      var yvar = vars[1]\n      var ylimits = limits[1]\n      var zvar = vars[2]\n      var zval = z\n      }\n   if (!isNaN(w))\n      h = Math.floor(w*(ylimits[1]-ylimits[0])/(xlimits[1]-xlimits[0]))\n   else\n      w = Math.floor(h*(xlimits[1]-xlimits[0])/(ylimits[1]-ylimits[0]))\n   mod.img.height = h\n   mod.img.width = w\n   var blob = new Blob(['('+worker.toString()+'())'])\n   var url = window.URL.createObjectURL(blob)\n   var webworker = new Worker(url)\n   webworker.addEventListener('message',function(evt) {\n      window.URL.revokeObjectURL(url)\n      var h = mod.img.height\n      var w = mod.img.width\n      var buf = new Uint8ClampedArray(evt.data.buffer)\n      var imgdata = new ImageData(buf,w,h)\n      var ctx = mod.img.getContext(\"2d\")\n      ctx.putImageData(imgdata,0,0)\n      if (w > h) {\n         var x0 = 0\n         var y0 = mod.canvas.height*.5*(1-h/w)\n         var wd = mod.canvas.width\n         var hd = mod.canvas.width*h/w\n         }\n      else {\n         var x0 = mod.canvas.width*.5*(1-w/h)\n         var y0 = 0\n         var wd = mod.canvas.height*w/h\n         var hd = mod.canvas.height\n         }\n      var ctx = mod.canvas.getContext(\"2d\")\n      ctx.fillStyle = '#dddddd'\n      ctx.fillRect(0,0,mod.canvas.width,mod.canvas.height)\n      ctx.drawImage(mod.img,x0,y0,wd,hd)\n      if (mod.win != null) {\n         var canvas = mod.win.document.getElementById(mod.div.id+'canvas')\n         var ctx = canvas.getContext(\"2d\")\n         canvas.width = window.innerWidth\n         canvas.height = window.innerWidth\n         var h = mod.img.height\n         var w = mod.img.width\n         if (w > h) {\n            var wd = canvas.width\n            var hd = canvas.width*h/w\n            }\n         else {\n            var wd = canvas.height*w/h\n            var hd = canvas.height\n            }\n         ctx.fillStyle = '#dddddd'\n         ctx.fillRect(0,0,canvas.width,canvas.height)\n         ctx.drawImage(mod.img,0,0,wd,hd)\n         }\n      webworker.terminate()\n      outputs.image.event()\n      })\n   var ctx = mod.canvas.getContext(\"2d\")\n   ctx.fillStyle = '#dddddd'\n   ctx.fillRect(0,0,mod.canvas.width,mod.canvas.height)\n   var ctx = mod.img.getContext(\"2d\")\n   ctx.fillStyle = '#dddddd'\n   ctx.fillRect(0,0,mod.img.width,mod.img.height)\n   var img = ctx.getImageData(0,0,mod.img.width,mod.img.height)\n   webworker.postMessage({\n      height:img.height,width:img.width,\n      xvar:xvar,yvar:yvar,zvar:zvar,zval:zval,\n      xlimits:xlimits,ylimits:ylimits,\n      function:fn,\n      buffer:img.data.buffer},\n      [img.data.buffer])\n   }\n//\n// worker\n//\nfunction worker() {\n   self.addEventListener('message',function(evt) {\n      var h = evt.data.height\n      var w = evt.data.width\n      var xvar = evt.data.xvar\n      var yvar = evt.data.yvar\n      var zvar = evt.data.zvar\n      var zval = evt.data.zval\n      var xlimits = evt.data.xlimits\n      var ylimits = evt.data.ylimits\n      var buf = new Uint8ClampedArray(evt.data.buffer)\n      var f = new Function(xvar,yvar,zvar,'return ('+evt.data.function+')')\n      var x,y,v\n      for (var row = 0; row < h; ++row) {\n         y = ylimits[0]+(ylimits[1]-ylimits[0])*row/(h-1)\n         for (var col = 0; col < w; ++col) {\n            x = xlimits[0]+(xlimits[1]-xlimits[0])*col/(w-1)\n            v = (f(x,y,zval) >= 0) ? 255 : 0\n            buf[(h-1-row)*w*4+col*4+0] = v\n            buf[(h-1-row)*w*4+col*4+1] = v\n            buf[(h-1-row)*w*4+col*4+2] = v\n            buf[(h-1-row)*w*4+col*4+3] = 255\n            }\n         }\n      self.postMessage({buffer:buf.buffer},[buf.buffer])\n      })\n   }\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"133","left":"2676","inputs":{},"outputs":{}},"0.7152788275346978":{"definition":"//\n// frep circle\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep circle'\n//\n// initialization\n//\nvar init = function() {\n   mod.x.value = '0.4'\n   mod.y.value = '0.4'\n   mod.radius.value = '0.16666666666666666'\n   }\n//\n// inputs\n//\nvar inputs = {\n   variables:{type:'',\n      event:function(evt){\n         for (var p in evt.detail)\n            mod[p].value = evt.detail[p]\n         outputs.variables.event()\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         var x = parseFloat(mod.x.value)\n         var y = parseFloat(mod.y.value)\n         var radius = parseFloat(mod.radius.value)\n         var fn = `((${radius})*(${radius})-((X-(${x}))*(X-(${x}))+(Y-(${y}))*(Y-(${y}))))`\n         var variables = ['X','Y']\n         var limits = [[x-radius,x+radius],[y-radius,y+radius]]\n         var type = 'Magnitude'\n         var shape = {function:fn,variables:variables,limits:limits,type:type}\n         mods.output(mod,'shape',shape)}\n         },\n   variables:{type:'',\n      event:function(){\n         var x = parseFloat(mod.x.value)\n         var y = parseFloat(mod.y.value)\n         var radius = parseFloat(mod.radius.value)\n         var vars = {x:x,y:y,radius:radius}\n         mods.output(mod,'variables',vars)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // x\n   //\n   div.appendChild(document.createTextNode('x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.x = input\n   //\n   // y\n   //\n   div.appendChild(document.createTextNode(' y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.y = input\n   div.appendChild(document.createElement('br'))\n   //\n   // r\n   //\n   div.appendChild(document.createTextNode('radius: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.radius = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.variables.event()\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"502","left":"666","inputs":{},"outputs":{}},"0.04772797317232935":{"definition":"//\n// construct object\n//\n// Neil Gershenfeld \n// (c) Massachusetts Institute of Technology 2018\n// \n// This work may be reproduced, modified, distributed, performed, and \n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is \n// provided as is; no warranty is provided, and users accept all \n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'construct object'\n//\n// initialization\n//\nvar init = function() {\n   mod.in0.value = '{\"x\":0,\"y\":0,\"radius\":1}'\n   mod.in1.value = '{}'\n   mod.out0.value = '{x:.4*in0.radius,y:.4*in0.radius,radius:in0.radius/6}'\n   mod.out1.value = '{}'\n   }\n//\n// inputs\n//\nvar inputs = {\n   in0:{type:'',label:'input 0',\n      event:function(evt) {\n         mod.in0.value = JSON.stringify(evt.detail)\n         construct_output()\n         }},\n   in1:{type:'',label:'input 1',\n      event:function(evt) {\n         mod.in1.value = JSON.stringify(evt.detail)\n         construct_output()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   out0:{type:'',label:'output 0',\n      event:function(arg){\n         mods.output(mod,'out0',arg)\n         }},\n   out1:{type:'',label:'output 1',\n      event:function(arg){\n         mods.output(mod,'out1',arg)\n         }}}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // inputs\n   //\n   div.appendChild(document.createTextNode('input 0:'))\n   div.appendChild(document.createElement('br'))\n   var text = document.createElement('textarea')\n      text.setAttribute('rows',1)\n      text.setAttribute('cols',mods.ui.cols)\n      div.appendChild(text)\n      mod.in0 = text\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('input 1:'))\n   div.appendChild(document.createElement('br'))\n   var text = document.createElement('textarea')\n      text.setAttribute('rows',1)\n      text.setAttribute('cols',mods.ui.cols)\n      div.appendChild(text)\n      mod.in1 = text\n   div.appendChild(document.createElement('br'))\n   //\n   // outputs\n   //\n   div.appendChild(document.createTextNode('output 0:'))\n   div.appendChild(document.createElement('br'))\n   var text = document.createElement('textarea')\n      text.setAttribute('rows',1)\n      text.setAttribute('cols',mods.ui.cols)\n      div.appendChild(text)\n      mod.out0 = text\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('output 1:'))\n   div.appendChild(document.createElement('br'))\n   var text = document.createElement('textarea')\n      text.setAttribute('rows',1)\n      text.setAttribute('cols',mods.ui.cols)\n      div.appendChild(text)\n      mod.out1 = text\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         construct_output()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\nfunction construct_output() {\n   var in0 = JSON.parse(mod.in0.value)\n   var in1 = JSON.parse(mod.in1.value)\n   eval('out0 ='+mod.out0.value)\n   eval('out1 ='+mod.out1.value)\n   outputs.out0.event(out0)\n   outputs.out1.event(out1)\n   }\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"454","left":"212","inputs":{},"outputs":{}},"0.9645985086194264":{"definition":"//\n// frep subtract\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2017\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep subtract'\n//\n// initialization\n//\nvar init = function() {\n   mod.shape0 = null\n   mod.shape1 = null\n   mod.fn0.value = ''\n   mod.fn1.value = ''\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape0:{type:'',label:'shape 0',\n      event:function(evt){\n         mod.shape0 = evt.detail\n         mod.fn0.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   shape1:{type:'',label:'shape 1',\n      event:function(evt){\n         mod.shape1 = evt.detail\n         mod.fn1.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   clear:{type:'',\n      event:function(evt){\n         mod.shape0 = null\n         mod.shape1 = null\n         mod.fn0.value = ''\n         mod.fn1.value = ''\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         if ((mod.shape0 != null) && (mod.shape1 != null)) {\n            var fn = `Math.min(${mod.shape0.function},-(${mod.shape1.function}))`\n            var variables = mod.shape0.variables\n            var type = mod.shape0.type        \n            var limits = []\n            for (var v = 0; v < mod.shape0.limits.length; ++v)\n               limits[v] = [mod.shape0.limits[v][0],mod.shape0.limits[v][1]]\n            var shape = {function:fn,variables:variables,limits:limits,type:type}\n            mods.output(mod,'shape',shape)}\n            }\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // function 0\n   //\n   div.appendChild(document.createTextNode('function 0: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn0 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // function 1\n   //\n   div.appendChild(document.createTextNode('function 1: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn1 = input\n   div.appendChild(document.createElement('br'))\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"186","left":"673","inputs":{},"outputs":{}},"0.9458395548196141":{"definition":"//\n// frep reflect\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep reflect'\n//\n// initialization\n//\nvar init = function() {\n   mod.origin0.value = '0'\n   mod.origin1.value = '0'\n   mod.x.checked = true\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'',\n      event:function(evt){\n         mod.shape = evt.detail\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         var fn = mod.shape.function\n         var variables = mod.shape.variables\n         var type = mod.shape.type        \n         var origin0 = parseFloat(mod.origin0.value)\n         var origin1 = parseFloat(mod.origin1.value)\n         var limits = []\n         for (var v = 0; v < mod.shape.limits.length; ++v) {\n            limits[v] = []\n            limits[v][0] = mod.shape.limits[v][0]\n            limits[v][1] = mod.shape.limits[v][1]\n            }\n         if (mod.x.checked) {\n            var xvar = variables[0]\n            var re = new RegExp(xvar,'g')\n            fn = fn.replace(re,`(${2*origin0}-(${xvar}))`)\n            var dx = mod.shape.limits[0][1]-mod.shape.limits[0][0]\n            var dl = mod.shape.limits[0][0]-origin0\n            limits[0][0] = origin0-(dl+dx)\n            limits[0][1] = origin0-dl\n            }\n         else if (mod.y.checked) {\n            var yvar = variables[1]\n            var re = new RegExp(yvar,'g')\n            fn = fn.replace(re,`(${2*origin0}-(${yvar}))`)\n            var dy = mod.shape.limits[1][1]-mod.shape.limits[1][0]\n            var dl = mod.shape.limits[1][0]-origin0\n            limits[1][0] = origin0-(dl+dy)\n            limits[1][1] = origin0-dl\n            }\n         else if (mod.z.checked) {\n            var zvar = variables[2]\n            var re = new RegExp(zvar,'g')\n            fn = fn.replace(re,`(${2*origin0}-(${zvar}))`)\n            var dz = mod.shape.limits[2][1]-mod.shape.limits[2][0]\n            var dl = mod.shape.limits[2][0]-origin0\n            limits[2][0] = origin0-(dl+dz)\n            limits[2][1] = origin0-dl\n            }\n         else if (mod.xy.checked) {\n            var xvar = variables[0]\n            var yvar = variables[1]\n            var xre = new RegExp(xvar,'g')\n            var yre = new RegExp(yvar,'g')\n            fn = fn.replace(xre,'TEMP')\n            fn = fn.replace(yre,`((${origin1})+(${xvar})-(${origin0}))`)\n            fn = fn.replace(/TEMP/g,`((${origin0})+(${yvar})-(${origin1}))`)\n            var dx = mod.shape.limits[0][1]-mod.shape.limits[0][0]\n            var dy = mod.shape.limits[1][1]-mod.shape.limits[1][0]\n            var dxl = mod.shape.limits[0][0]-origin0\n            var dyl = mod.shape.limits[1][0]-origin1\n            limits[0][0] = origin0+dyl\n            limits[0][1] = origin0+dyl+dy\n            limits[1][0] = origin1+dxl\n            limits[1][1] = origin1+dxl+dx\n            }\n         else if (mod.xz.checked) {\n            var xvar = variables[0]\n            var zvar = variables[2]\n            var xre = new RegExp(xvar,'g')\n            var zre = new RegExp(zvar,'g')\n            fn = fn.replace(xre,'TEMP')\n            fn = fn.replace(zre,`((${origin1})+(${xvar})-(${origin0}))`)\n            fn = fn.replace(/TEMP/g,`((${origin0})+(${zvar})-(${origin1}))`)\n            var dx = mod.shape.limits[0][1]-mod.shape.limits[0][0]\n            var dz = mod.shape.limits[2][1]-mod.shape.limits[2][0]\n            var dxl = mod.shape.limits[0][0]-origin0\n            var dzl = mod.shape.limits[2][0]-origin1\n            limits[0][0] = origin0+dzl\n            limits[0][1] = origin0+dzl+dz\n            limits[2][0] = origin1+dxl\n            limits[2][1] = origin1+dxl+dx\n            }\n         else if (mod.yz.checked) {\n            var yvar = variables[1]\n            var zvar = variables[2]\n            var yre = new RegExp(yvar,'g')\n            var zre = new RegExp(zvar,'g')\n            fn = fn.replace(yre,'TEMP')\n            fn = fn.replace(zre,`((${origin1})+(${yvar})-(${origin0}))`)\n            fn = fn.replace(/TEMP/g,`((${origin0})+(${zvar})-(${origin1}))`)\n            var dy = mod.shape.limits[1][1]-mod.shape.limits[1][0]\n            var dz = mod.shape.limits[2][1]-mod.shape.limits[2][0]\n            var dyl = mod.shape.limits[1][0]-origin0\n            var dzl = mod.shape.limits[2][0]-origin1\n            limits[1][0] = origin0+dzl\n            limits[1][1] = origin0+dzl+dz\n            limits[2][0] = origin1+dyl\n            limits[2][1] = origin1+dyl+dy\n            }\n         var shape = {function:fn,variables:variables,limits:limits,type:type}\n         mods.output(mod,'shape',shape)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // axis\n   //\n   div.appendChild(document.createTextNode('axis: '))\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('x'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      input.id = mod.div.id+'x'\n      div.appendChild(input)\n      mod.x = input\n   div.appendChild(document.createTextNode(' y'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      input.id = mod.div.id+'y'\n      div.appendChild(input)\n      mod.y = input\n   div.appendChild(document.createTextNode(' z'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      input.id = mod.div.id+'z'\n      div.appendChild(input)\n      mod.z = input\n   div.appendChild(document.createElement('br'))\n   //\n   // origin 0\n   //\n   div.appendChild(document.createTextNode('origin 0: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.origin0 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // axis\n   //\n   div.appendChild(document.createTextNode('xy'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      input.id = mod.div.id+'xy'\n      div.appendChild(input)\n      mod.xy = input\n   div.appendChild(document.createTextNode(' xz'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      input.id = mod.div.id+'xz'\n      div.appendChild(input)\n      mod.xz = input\n   div.appendChild(document.createTextNode(' yz'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      input.id = mod.div.id+'yz'\n      div.appendChild(input)\n      mod.yz = input\n   div.appendChild(document.createElement('br'))\n   //\n   // origin 1\n   //\n   div.appendChild(document.createTextNode('origin 1: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.origin1 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"501","left":"1033","inputs":{},"outputs":{}},"0.04930175848785401":{"definition":"//\n// frep subtract\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2017\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep subtract'\n//\n// initialization\n//\nvar init = function() {\n   mod.shape0 = null\n   mod.shape1 = null\n   mod.fn0.value = 'Math.min(((1)*(1)-((X-(0))*(X-(0))+(Y-(0))*(Y-(0)))),-(((0.16666666666666666)*(0.16666666666666666)-((X-(0.4))*(X-(0.4))+(Y-(0.4))*(Y-(0.4))))))'\n   mod.fn1.value = '((0.16666666666666666)*(0.16666666666666666)-(((0-(X))-(0.4))*((0-(X))-(0.4))+(Y-(0.4))*(Y-(0.4))))'\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape0:{type:'',label:'shape 0',\n      event:function(evt){\n         mod.shape0 = evt.detail\n         mod.fn0.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   shape1:{type:'',label:'shape 1',\n      event:function(evt){\n         mod.shape1 = evt.detail\n         mod.fn1.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   clear:{type:'',\n      event:function(evt){\n         mod.shape0 = null\n         mod.shape1 = null\n         mod.fn0.value = ''\n         mod.fn1.value = ''\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         if ((mod.shape0 != null) && (mod.shape1 != null)) {\n            var fn = `Math.min(${mod.shape0.function},-(${mod.shape1.function}))`\n            var variables = mod.shape0.variables\n            var type = mod.shape0.type        \n            var limits = []\n            for (var v = 0; v < mod.shape0.limits.length; ++v)\n               limits[v] = [mod.shape0.limits[v][0],mod.shape0.limits[v][1]]\n            var shape = {function:fn,variables:variables,limits:limits,type:type}\n            mods.output(mod,'shape',shape)}\n            }\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // function 0\n   //\n   div.appendChild(document.createTextNode('function 0: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn0 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // function 1\n   //\n   div.appendChild(document.createTextNode('function 1: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn1 = input\n   div.appendChild(document.createElement('br'))\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"183","left":"1033","inputs":{},"outputs":{}},"0.5608762029437723":{"definition":"//\n// frep scale\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep scale'\n//\n// initialization\n//\nvar init = function() {\n   mod.ox.value = '0'\n   mod.oy.value = '0'\n   mod.oz.value = ''\n   mod.sx.value = '.7'\n   mod.sy.value = '.7'\n   mod.sz.value = ''\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'',\n      event:function(evt){\n         mod.shape = evt.detail\n         outputs.shape.event()\n         }},\n   variables:{type:'',\n      event:function(evt){\n         for (var p in evt.detail)\n            mod[p].value = evt.detail[p]\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         var fn = mod.shape.function\n         var variables = mod.shape.variables\n         var type = mod.shape.type        \n         var limits = []\n         for (var v = 0; v < mod.shape.limits.length; ++v) {\n            limits[v] = []\n            limits[v][0] = mod.shape.limits[v][0]\n            limits[v][1] = mod.shape.limits[v][1]\n            }\n         if (mod.ox.value != '') {\n            var ox = parseFloat(mod.ox.value)\n            var sx = parseFloat(mod.sx.value)\n            var xvar = variables[0]\n            var re = new RegExp(xvar,'g')\n            fn = fn.replace(re,`((${ox})+(${xvar}-(${ox}))/(${sx}))`)\n            limits[0][0] = ox+(limits[0][0]-ox)*sx\n            limits[0][1] = ox+(limits[0][1]-ox)*sx\n            }\n         if (mod.oy.value != '') {\n            var oy = parseFloat(mod.oy.value)\n            var sy = parseFloat(mod.sy.value)\n            var yvar = variables[1]\n            var re = new RegExp(yvar,'g')\n            fn = fn.replace(re,`((${oy})+(${yvar}-(${oy}))/(${sy}))`)\n            limits[1][0] = oy+(limits[1][0]-oy)*sy\n            limits[1][1] = oy+(limits[1][1]-oy)*sy\n            }\n         if (mod.oz.value != '') {\n            var oz = parseFloat(mod.oz.value)\n            var sz = parseFloat(mod.sz.value)\n            var zvar = variables[2]\n            var re = new RegExp(zvar,'g')\n            fn = fn.replace(re,`((${oz})+(${zvar}-(${oz}))/(${sz}))`)\n            limits[2][0] = oz+(limits[2][0]-oz)*sz\n            limits[2][1] = oz+(limits[2][1]-oz)*sz\n            }\n         var shape = {function:fn,variables:variables,limits:limits,type:type}\n         mods.output(mod,'shape',shape)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // origin\n   //\n   div.appendChild(document.createTextNode('origin x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.ox = input\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.oy = input\n   div.appendChild(document.createTextNode(' z: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.oz = input\n   div.appendChild(document.createElement('br'))\n   //\n   // scale\n   //\n   div.appendChild(document.createTextNode('scale x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.sx = input\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.sy = input\n   div.appendChild(document.createTextNode(' z: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.sz = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"528","left":"1444","inputs":{},"outputs":{}},"0.40238136387777756":{"definition":"//\n// frep subtract\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2017\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep subtract'\n//\n// initialization\n//\nvar init = function() {\n   mod.shape0 = null\n   mod.shape1 = null\n   mod.fn0.value = 'Math.min(Math.min(((1)*(1)-((X-(0))*(X-(0))+(Y-(0))*(Y-(0)))),-(((0.16666666666666666)*(0.16666666666666666)-((X-(0.4))*(X-(0.4))+(Y-(0.4))*(Y-(0.4)))))),-(((0.16666666666666666)*(0.16666666666666666)-(((0-(X))-(0.4))*((0-(X))-(0.4))+(Y-(0.4))*(Y-(0.4))))))'\n   mod.fn1.value = 'Math.min(((0)-Y),(Math.min(((1)*(1)-((((0)+(X-(0))/(0.7))-(0))*(((0)+(X-(0))/(0.7))-(0))+(((0)+(Y-(0))/(0.7))-(0))*(((0)+(Y-(0))/(0.7))-(0)))),-(((1)*(1)-((((0)+(((0)+(X-(0))/(0.75))-(0))/(0.7))-(0))*(((0)+(((0)+(X-(0))/(0.75))-(0))/(0.7))-(0))+(((0)+(((0)+(Y-(0))/(0.75))-(0))/(0.7))-(0))*(((0)+(((0)+(Y-(0))/(0.75))-(0))/(0.7))-(0))))))))'\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape0:{type:'',label:'shape 0',\n      event:function(evt){\n         mod.shape0 = evt.detail\n         mod.fn0.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   shape1:{type:'',label:'shape 1',\n      event:function(evt){\n         mod.shape1 = evt.detail\n         mod.fn1.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   clear:{type:'',\n      event:function(evt){\n         mod.shape0 = null\n         mod.shape1 = null\n         mod.fn0.value = ''\n         mod.fn1.value = ''\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         if ((mod.shape0 != null) && (mod.shape1 != null)) {\n            var fn = `Math.min(${mod.shape0.function},-(${mod.shape1.function}))`\n            var variables = mod.shape0.variables\n            var type = mod.shape0.type        \n            var limits = []\n            for (var v = 0; v < mod.shape0.limits.length; ++v)\n               limits[v] = [mod.shape0.limits[v][0],mod.shape0.limits[v][1]]\n            var shape = {function:fn,variables:variables,limits:limits,type:type}\n            mods.output(mod,'shape',shape)}\n            }\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // function 0\n   //\n   div.appendChild(document.createTextNode('function 0: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn0 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // function 1\n   //\n   div.appendChild(document.createTextNode('function 1: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn1 = input\n   div.appendChild(document.createElement('br'))\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"173","left":"1392","inputs":{},"outputs":{}},"0.5939459494005885":{"definition":"//\n// frep scale\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep scale'\n//\n// initialization\n//\nvar init = function() {\n   mod.ox.value = '0'\n   mod.oy.value = '0'\n   mod.oz.value = ''\n   mod.sx.value = '.75'\n   mod.sy.value = '.75'\n   mod.sz.value = ''\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'',\n      event:function(evt){\n         mod.shape = evt.detail\n         outputs.shape.event()\n         }},\n   variables:{type:'',\n      event:function(evt){\n         for (var p in evt.detail)\n            mod[p].value = evt.detail[p]\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         var fn = mod.shape.function\n         var variables = mod.shape.variables\n         var type = mod.shape.type        \n         var limits = []\n         for (var v = 0; v < mod.shape.limits.length; ++v) {\n            limits[v] = []\n            limits[v][0] = mod.shape.limits[v][0]\n            limits[v][1] = mod.shape.limits[v][1]\n            }\n         if (mod.ox.value != '') {\n            var ox = parseFloat(mod.ox.value)\n            var sx = parseFloat(mod.sx.value)\n            var xvar = variables[0]\n            var re = new RegExp(xvar,'g')\n            fn = fn.replace(re,`((${ox})+(${xvar}-(${ox}))/(${sx}))`)\n            limits[0][0] = ox+(limits[0][0]-ox)*sx\n            limits[0][1] = ox+(limits[0][1]-ox)*sx\n            }\n         if (mod.oy.value != '') {\n            var oy = parseFloat(mod.oy.value)\n            var sy = parseFloat(mod.sy.value)\n            var yvar = variables[1]\n            var re = new RegExp(yvar,'g')\n            fn = fn.replace(re,`((${oy})+(${yvar}-(${oy}))/(${sy}))`)\n            limits[1][0] = oy+(limits[1][0]-oy)*sy\n            limits[1][1] = oy+(limits[1][1]-oy)*sy\n            }\n         if (mod.oz.value != '') {\n            var oz = parseFloat(mod.oz.value)\n            var sz = parseFloat(mod.sz.value)\n            var zvar = variables[2]\n            var re = new RegExp(zvar,'g')\n            fn = fn.replace(re,`((${oz})+(${zvar}-(${oz}))/(${sz}))`)\n            limits[2][0] = oz+(limits[2][0]-oz)*sz\n            limits[2][1] = oz+(limits[2][1]-oz)*sz\n            }\n         var shape = {function:fn,variables:variables,limits:limits,type:type}\n         mods.output(mod,'shape',shape)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // origin\n   //\n   div.appendChild(document.createTextNode('origin x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.ox = input\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.oy = input\n   div.appendChild(document.createTextNode(' z: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.oz = input\n   div.appendChild(document.createElement('br'))\n   //\n   // scale\n   //\n   div.appendChild(document.createTextNode('scale x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.sx = input\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.sy = input\n   div.appendChild(document.createTextNode(' z: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.sz = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"585","left":"1849","inputs":{},"outputs":{}},"0.690161531242695":{"definition":"//\n// frep subtract\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2017\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep subtract'\n//\n// initialization\n//\nvar init = function() {\n   mod.shape0 = null\n   mod.shape1 = null\n   mod.fn0.value = ''\n   mod.fn1.value = ''\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape0:{type:'',label:'shape 0',\n      event:function(evt){\n         mod.shape0 = evt.detail\n         mod.fn0.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   shape1:{type:'',label:'shape 1',\n      event:function(evt){\n         mod.shape1 = evt.detail\n         mod.fn1.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   clear:{type:'',\n      event:function(evt){\n         mod.shape0 = null\n         mod.shape1 = null\n         mod.fn0.value = ''\n         mod.fn1.value = ''\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         if ((mod.shape0 != null) && (mod.shape1 != null)) {\n            var fn = `Math.min(${mod.shape0.function},-(${mod.shape1.function}))`\n            var variables = mod.shape0.variables\n            var type = mod.shape0.type        \n            var limits = []\n            for (var v = 0; v < mod.shape0.limits.length; ++v)\n               limits[v] = [mod.shape0.limits[v][0],mod.shape0.limits[v][1]]\n            var shape = {function:fn,variables:variables,limits:limits,type:type}\n            mods.output(mod,'shape',shape)}\n            }\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // function 0\n   //\n   div.appendChild(document.createTextNode('function 0: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn0 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // function 1\n   //\n   div.appendChild(document.createTextNode('function 1: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn1 = input\n   div.appendChild(document.createElement('br'))\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"606","left":"2209","inputs":{},"outputs":{}},"0.19288167008415902":{"definition":"//\n// frep slice\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep slice'\n//\n// initialization\n//\nvar init = function() {\n   mod.x0.value = ''\n   mod.x1.value = ''\n   mod.y0.value = ''\n   mod.y1.value = '0'\n   mod.z0.value = ''\n   mod.z1.value = ''\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'',\n      event:function(evt){\n         mod.shape = evt.detail\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         var limits = []\n         for (var v = 0; v < mod.shape.limits.length; ++v) {\n            limits[v] = []\n            limits[v][0] = mod.shape.limits[v][0]\n            limits[v][1] = mod.shape.limits[v][1]\n            }\n         var variables = mod.shape.variables\n         var fn = mod.shape.function\n         if (mod.x0.value != '') {\n            var x0 = parseFloat(mod.x0.value)\n            var xvar = variables[0]\n            fn = `Math.min((${xvar}-(${x0})),(${fn}))`\n            limits[0][0] = Math.max(limits[0][0],x0)\n            }\n         if (mod.x1.value != '') {\n            var x1 = parseFloat(mod.x1.value)\n            var xvar = variables[0]\n            fn = `Math.min(((${x1})-${xvar}),(${fn}))`\n            limits[0][1] = Math.min(limits[0][1],x1)\n            }\n         if (mod.y0.value != '') {\n            var y0 = parseFloat(mod.y0.value)\n            var yvar = variables[1]\n            fn = `Math.min((${yvar}-(${y0})),(${fn}))`\n            limits[1][0] = Math.max(limits[1][0],y0)\n            }\n         if (mod.y1.value != '') {\n            var y1 = parseFloat(mod.y1.value)\n            var yvar = variables[1]\n            fn = `Math.min(((${y1})-${yvar}),(${fn}))`\n            limits[1][1] = Math.min(limits[1][1],y1)\n            }\n         if (mod.z0.value != '') {\n            var z0 = parseFloat(mod.z0.value)\n            var zvar = variables[2]\n            fn = `Math.min((${zvar}-(${z0})),(${fn}))`\n            limits[2][0] = Math.max(limits[2][0],z0)\n            }\n         if (mod.z1.value != '') {\n            var z1 = parseFloat(mod.z1.value)\n            var zvar = variables[2]\n            fn = `Math.min(((${z1})-${zvar}),(${fn}))`\n            limits[2][1] = Math.min(limits[2][1],z1)\n            }\n         var shape = {function:fn,variables:mod.shape.variables,limits:limits,type:mod.shape.type}\n         mod.fn.value = fn\n         mods.output(mod,'shape',shape)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // x0\n   //\n   div.appendChild(document.createTextNode('x0: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.x0 = input\n   //\n   // x1\n   //\n   div.appendChild(document.createTextNode(' x1: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.x1 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // y0\n   //\n   div.appendChild(document.createTextNode('y0: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.y0 = input\n   //\n   // y1\n   //\n   div.appendChild(document.createTextNode(' y1: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.y1 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // z0\n   //\n   div.appendChild(document.createTextNode('z0: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.z0 = input\n   //\n   // z1\n   //\n   div.appendChild(document.createTextNode(' z1: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.z1 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // function\n   //\n   div.appendChild(document.createTextNode('function: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"267","left":"1783","inputs":{},"outputs":{}},"0.8080126368305371":{"definition":"//\n// frep taper \n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep taper'\n//\n// initialization\n//\nvar init = function() {\n   mod.variable0.value = '-1'\n   mod.variable1.value = '1'\n   mod.scale0.value = '.5'\n   mod.scale1.value = '2'\n   mod.originx.value = '0'\n   mod.originy.value = '0'\n   mod.xy.checked = true\n   mod.xz.checked = false\n   mod.yz.checked = false\n   mod.xyz.checked = false\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'',\n      event:function(evt){\n         mod.shape = evt.detail\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         var fn = mod.shape.function\n         var variables = mod.shape.variables\n         var type = mod.shape.type        \n         var var0 = parseFloat(mod.variable0.value)\n         var var1 = parseFloat(mod.variable1.value)\n         var dvar = var1-var0\n         var s0 = parseFloat(mod.scale0.value)\n         var s1 = parseFloat(mod.scale1.value)\n         var ds = s1-s0\n         var ox = parseFloat(mod.originx.value)\n         var oy = parseFloat(mod.originy.value)\n         var limits = []\n         for (var v = 0; v < mod.shape.limits.length; ++v) {\n            limits[v] = []\n            limits[v][0] = mod.shape.limits[v][0]\n            limits[v][1] = mod.shape.limits[v][1]\n            }\n         if (mod.xy.checked) {\n            var xvar = variables[0]\n            var yvar = variables[1]\n            var re = new RegExp(xvar,'g')\n            fn = fn.replace(re,`((${ox})+(${xvar}-(${ox}))/((${s0})+(${ds})*(${yvar}-(${var0}))/(${dvar})))`)\n            var xmin = limits[0][0]\n            var xmax = limits[0][1]\n            var ymin = limits[1][0]\n            var ymax = limits[1][1]\n            var x00 = ox+(xmin-ox)*(s0+ds*(ymin-var0)/dvar)\n            var x01 = ox+(xmin-ox)*(s0+ds*(ymax-var0)/dvar)\n            limits[0][0] = Math.min(x00,x01)\n            var x10 = ox+(xmax-ox)*(s0+ds*(ymin-var0)/dvar)\n            var x11 = ox+(xmax-ox)*(s0+ds*(ymax-var0)/dvar)\n            limits[0][1] = Math.max(x10,x11)\n            }\n         else if (mod.xz.checked) {\n            var xvar = variables[0]\n            var zvar = variables[2]\n            var re = new RegExp(xvar,'g')\n            fn = fn.replace(re,`((${ox})+(${xvar}-(${ox}))/((${s0})+(${ds})*(${zvar}-(${var0}))/(${dvar})))`)\n            var xmin = limits[0][0]\n            var xmax = limits[0][1]\n            var zmin = limits[2][0]\n            var zmax = limits[2][1]\n            var x00 = ox+(xmin-ox)*(s0+ds*(zmin-var0)/dvar)\n            var x01 = ox+(xmin-ox)*(s0+ds*(zmax-var0)/dvar)\n            limits[0][0] = Math.min(x00,x01)\n            var x10 = ox+(xmax-ox)*(s0+ds*(zmin-var0)/dvar)\n            var x11 = ox+(xmax-ox)*(s0+ds*(zmax-var0)/dvar)\n            limits[0][1] = Math.max(x10,x11)\n            }\n         else if (mod.yz.checked) {\n            var yvar = variables[1]\n            var zvar = variables[2]\n            var re = new RegExp(yvar,'g')\n            fn = fn.replace(re,`((${oy})+(${yvar}-(${oy}))/((${s0})+(${ds})*(${zvar}-(${var0}))/(${dvar})))`)\n            var ymin = limits[1][0]\n            var ymax = limits[1][1]\n            var zmin = limits[2][0]\n            var zmax = limits[2][1]\n            var y00 = oy+(ymin-oy)*(s0+ds*(zmin-var0)/dvar)\n            var y01 = oy+(ymin-oy)*(s0+ds*(zmax-var0)/dvar)\n            limits[1][0] = Math.min(y00,y01)\n            var y10 = oy+(ymax-oy)*(s0+ds*(zmin-var0)/dvar)\n            var y11 = oy+(ymax-oy)*(s0+ds*(zmax-var0)/dvar)\n            limits[1][1] = Math.max(y10,y11)\n            }\n         else if (mod.xyz.checked) {\n            var xvar = variables[0]\n            var yvar = variables[1]\n            var zvar = variables[2]\n            var xre = new RegExp(xvar,'g')\n            var yre = new RegExp(yvar,'g')\n            fn = fn.replace(xre,`((${ox})+(${xvar}-(${ox}))/((${s0})+(${ds})*(${zvar}-(${var0}))/(${dvar})))`)\n            fn = fn.replace(yre,`((${oy})+(${yvar}-(${oy}))/((${s0})+(${ds})*(${zvar}-(${var0}))/(${dvar})))`)\n            var xmin = limits[0][0]\n            var xmax = limits[0][1]\n            var zmin = limits[2][0]\n            var zmax = limits[2][1]\n            var x00 = ox+(xmin-ox)*(s0+ds*(zmin-var0)/dvar)\n            var x01 = ox+(xmin-ox)*(s0+ds*(zmax-var0)/dvar)\n            limits[0][0] = Math.min(x00,x01)\n            var x10 = ox+(xmax-ox)*(s0+ds*(zmin-var0)/dvar)\n            var x11 = ox+(xmax-ox)*(s0+ds*(zmax-var0)/dvar)\n            limits[0][1] = Math.max(x10,x11)\n            var ymin = limits[1][0]\n            var ymax = limits[1][1]\n            var y00 = oy+(ymin-oy)*(s0+ds*(zmin-var0)/dvar)\n            var y01 = oy+(ymin-oy)*(s0+ds*(zmax-var0)/dvar)\n            limits[1][0] = Math.min(y00,y01)\n            var y10 = oy+(ymax-oy)*(s0+ds*(zmin-var0)/dvar)\n            var y11 = oy+(ymax-oy)*(s0+ds*(zmax-var0)/dvar)\n            limits[1][1] = Math.max(y10,y11)\n            }\n         var shape = {function:fn,variables:variables,limits:limits,type:type}\n         mods.output(mod,'shape',shape)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // direction \n   //\n   div.appendChild(document.createTextNode('direction: '))\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('x(y)'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      div.appendChild(input)\n      mod.xy = input\n   div.appendChild(document.createTextNode(' x(z)'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      div.appendChild(input)\n      mod.xz = input\n   div.appendChild(document.createTextNode(' y(z)'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      div.appendChild(input)\n      mod.yz = input\n   div.appendChild(document.createTextNode(' xy(z)'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      div.appendChild(input)\n      mod.xyz = input\n   div.appendChild(document.createElement('br'))\n   //\n   // variable 0\n   //\n   div.appendChild(document.createTextNode('at: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.variable0 = input\n   //\n   // scale 0\n   //\n   div.appendChild(document.createTextNode(' scale by: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.scale0 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // variable 1\n   //\n   div.appendChild(document.createTextNode('at: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.variable1 = input\n   //\n   // scale 1\n   //\n   div.appendChild(document.createTextNode(' scale by: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.scale1 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // x origin\n   //\n   div.appendChild(document.createTextNode('origin x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.originx = input\n   //\n   // y origin\n   //\n   div.appendChild(document.createTextNode(' y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.originy = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"147","left":"2148","inputs":{},"outputs":{}},"0.01016844222037161":{"definition":"//\n// frep inflate\n//    todo: better Z limit\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep inflate'\n//\n// initialization\n//\nvar init = function() {\n   mod.scale.value = '1'\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'2D',\n      event:function(evt){\n         mod.shape = evt.detail\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'3D',\n      event:function(){\n         var variables = []\n         variables[0] = mod.shape.variables[0]\n         variables[1] = mod.shape.variables[1]\n         variables[2] = 'Z'\n         var scale = parseFloat(mod.scale.value)\n         var limits = []\n         limits[0] = [mod.shape.limits[0][0],mod.shape.limits[0][1]]\n         limits[1] = [mod.shape.limits[1][0],mod.shape.limits[1][1]]\n         limits[2] = [0,limits[0][1]-limits[0][0]]\n         fn = `((${scale})*(${mod.shape.function})-Z)`\n         fn = `Math.min(${mod.shape.function},${fn})`\n         fn = `Math.min(Z,${fn})`\n         var shape = {function:fn,variables:variables,limits:limits,type:mod.shape.type}\n         mod.fn.value = fn\n         mods.output(mod,'shape',shape)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // scale\n   //\n   div.appendChild(document.createTextNode('scale: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.scale = input\n   div.appendChild(document.createElement('br'))\n   //\n   // function\n   //\n   div.appendChild(document.createTextNode('function: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"909","left":"2234","inputs":{},"outputs":{}},"0.43117078925934216":{"definition":"//\n// frep GPU volume renderer\n//\n// Neil Gershenfeld and Amira Abdel-Rahman\n// (c) Massachusetts Institute of Technology 2016\n// \n// This work may be reproduced, modified, distributed, performed, and \n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is \n// provided as is; no warranty is provided, and users accept all \n// liability.\n//\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {};\n//\n// name\n//\nvar name = 'render GPU';\n//\n// initialization\n//\nvar init = function() {\n   mod.steps.value=256.0;\n   mod.alphaCorrection=10.0;\n   mod.rendType=\"0\";\n   mod.windowOpen=false;\n   mod.xLimit1 =-1.0 ;\n   mod.xLimit2 =1.0 ; \n   mod.yLimit1 =-1.0 ; \n   mod.yLimit2 =1.0 ; \n   mod.zLimit1 =-1.0 ; \n   mod.zLimit2 =1.0 ;\n   mod.height=10.0;\n   mod.width=10.0;\n   mod.rendPerformance=0;\n   };\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'frep',\n   event:function(evt){\n\n      mod.shape=evt.detail;\n\n      // outputs.messageLog.event(mod.shape.limits);\n\n      //get largerst range and rescale other ones to adjust limit mapping\n      var tempIndex=0;\n      var tempMax=-1.0;\n\n      for(i=0;i<mod.shape.limits.length;i++)\n      {\n         if((mod.shape.limits[i][1]-mod.shape.limits[i][0]) >= tempMax )\n         {\n            tempIndex=i;\n            tempMax=mod.shape.limits[i][1]-mod.shape.limits[i][0];\n         }\n      }\n      for(i=0;i < mod.shape.limits.length;i++)\n      {\n         if(i!=tempIndex)\n         {\n            var tempDif = (mod.shape.limits[tempIndex][1]-mod.shape.limits[tempIndex][0])-(mod.shape.limits[i][1]-mod.shape.limits[i][0]);\n            mod.shape.limits[i][0]-=tempDif/2.0;\n            mod.shape.limits[i][1]+=tempDif/2.0;\n            \n         }\n      }\n\n      mod.xLimit1=mod.shape.limits[0][0] ;\n      mod.xLimit2=mod.shape.limits[0][1] ; \n      mod.yLimit1=mod.shape.limits[1][0] ; \n      mod.yLimit2=mod.shape.limits[1][1] ; \n      mod.zLimit1=mod.shape.limits[2][0] ; \n      mod.zLimit2=mod.shape.limits[2][1] ;\n      \n      //\n      //turn function string to glsl\n\t  //\n\t  \n\t  //remove all Math.\n      var str1 = mod.shape.function;\n\t  str1=str1.replace(/Math./g, '');\n\t  \n\t  //change atan2 functions to atan\n\t  str1=str1.replace(/atan2/g, \"atan\");\n         \n      //change all % to mod(,)\n      while(str1.indexOf(\"%\")>-1) //While '%' is there\n      {\n         //get location\n         var modLocation=str1.indexOf(\"%\");\n         //replace with ','\n         str1=str1.replace(/%/, \",\");\n         outputs.messageLog.event(\"1:\"+str1);\n\n         //parse before\n         var counterBefore=modLocation;\n         var count=0;\n         if(str1[--counterBefore]==')')\n         {\n            count++;\n            while(count>0)\n            {\n               counterBefore--;\n               if(str1[counterBefore]==')')\n               {\n                  count++;\n\n               }else if (str1[counterBefore]=='(')\n               {\n                  count--;\n               }\n            }\n         }else{\n            while(!isNaN(str1[counterBefore]) ||(str1[counterBefore]=='.')||(str1[counterBefore]=='X') ||(str1[counterBefore]=='Y')||(str1[counterBefore]=='Z'))\n            {\n               counterBefore--;\n            }\n\n         }\n         \n         \n         //parse after\n         var counterAfter=modLocation;\n         count=0;\n         if(str1[++counterAfter]=='(')\n         {\n            count++;\n            while(count>0)\n            {\n               counterAfter++;\n               if(str1[counterAfter]=='(')\n               {\n                  count++;\n\n               }else if (str1[counterAfter]==')')\n               {\n                  count--;\n               }\n            }\n         }else\n         {\n            while(!isNaN(str1[counterAfter]) ||(str1[counterAfter]=='.')||(str1[counterAfter]=='X') ||(str1[counterAfter]=='Y')||(str1[counterAfter]=='Z'))\n            {\n               counterAfter++;\n            }\n         }\n         \n         str1 = str1.substr(0, counterAfter) + \")\" + str1.substr(counterAfter);\n         str1 = str1.substr(0, counterBefore) + \"mod(\" + str1.substr(counterBefore);\n      }\n\n      //turn all ints to floatS\n      var str='';\n      for(var i=0;i<str1.length;i++)\n      {\n         //if number\n         if(!isNaN(str1[i]))\n         {\n            str+=str1[i];\n            //check next value\n            for(var j=i+1;j<str1.length;j++)\n            {\n            //if number add and continue\n            if(!isNaN(str1[j])) \n            {\n               str+=str1[j];\n               i=j;\n            }\n            //else if dot add and add numbers till NaN\n            else if(str1[j]=='.')\n            {\n               str+=str1[j];\n               i=j;\n               //add till not num\n               for(var k=j+1;k<str1.length;k++)\n               {\n                  if( ( !isNaN(str1[k]) )||str1[k]=='e')\n                  {\n                     //fix for scientific notation\n                     if(str1[k]=='e' && str1[k+1]=='-')\n                     {\n                        str+=str1[k];\n                        i=k;\n\n                        k++;\n\n                        str+=str1[k];\n                        i=k;\n\n                     }else\n                     {\n                        str+=str1[k];\n                        i=k;\n\n                     }\n                     \n                  }\n                  else\n                  {\n                     k=str1.length;\n                  }\n               }\n               j=str1.length;\n            }\n            //else add .0 and go to next number\n            else\n            {\n               str+='.';\n               str+='0';\n               j=str1.length;\n            }\n            }\n\n         }\n         else\n         {\n            str+=str1[i];\n         }\n      }\n      \n      mod.str=str;\n      outputs.messageLog.event(str);\n\n      //if window open update shader function\n      if(mod.windowOpen)\n      {\n         mod.updateShaderFunction();\n      }\n\n      }}};\n//\n// outputs\n//\nvar outputs = {\n    messageLog:{type:'string',\n      event:function(mess){\n      //show processed function\n        mods.output(mod,'messageLog',mess);\n      }\n    }\n}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // on-screen drawing canvas\n   //\n   var canvas = document.createElement('canvas');\n      canvas.width = mods.ui.canvas;\n      canvas.height = mods.ui.canvas;\n      canvas.style.backgroundColor = 'rgb(0,0,0)';\n      div.appendChild(canvas);\n      mod.canvas = canvas;\n   div.appendChild(document.createElement('br'));\n   //\n   // resolution\n   //\n   div.appendChild(document.createTextNode('resolution: '));\n   var input = document.createElement('input');\n      input.type = 'text';\n      input.size = 3;\n      input.addEventListener('input',function(){\n         if(mod.windowOpen)\n         {\n            mod.redraw(true);\n         }\n         });\n      div.appendChild(input);\n      mod.steps = input;\n   div.appendChild(document.createElement('br'));\n   //\n   // adaptive rendering\n   //\n   div.appendChild(document.createTextNode('rendering performance: '))\n            var input = document.createElement('SELECT');\n            \n         input.setAttribute(\"id\", \"rend-adpselect\");\n         \n         //select menu for functions\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"0\");\n         var t = document.createTextNode('constant');\n         z.appendChild(t);\n         input.appendChild(z);\n\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"1\");\n         var t = document.createTextNode('adaptive');\n         z.appendChild(t);\n         input.appendChild(z);\n         input.addEventListener('change',function(evt){\n            var temp= document.getElementById(\"rend-adpselect\");\n            mod.rendPerformance=parseInt(temp.value);\n            mod.updateShaderFunction();\n            });\n\n         div.appendChild(input);\n  \n   div.appendChild(document.createElement('br'));\n   //\n   // rendering style\n   //\n   div.appendChild(document.createTextNode('rendering style: '))\n            var input = document.createElement('SELECT');\n            \n         input.setAttribute(\"id\", \"rend-select\");\n         \n         //select menu for functions\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"0\");\n         var t = document.createTextNode('default');\n         z.appendChild(t);\n         input.appendChild(z);\n\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"1\");\n         var t = document.createTextNode('xray');\n         z.appendChild(t);\n         input.appendChild(z);\n\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"2\");\n         var t = document.createTextNode('height map (fixed)');\n         z.appendChild(t);\n         input.appendChild(z);\n\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"3\");\n         var t = document.createTextNode('height map (variable)');\n         z.appendChild(t);\n         input.appendChild(z);\n\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"4\");\n         var t = document.createTextNode('normals');\n         z.appendChild(t);\n         input.appendChild(z);\n\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"5\");\n         var t = document.createTextNode('light');\n         z.appendChild(t);\n         input.appendChild(z);\n\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"6\");\n         var t = document.createTextNode('specular');\n         z.appendChild(t);\n         input.appendChild(z);\n       \n         input.addEventListener('change',function(evt){\n            var temp= document.getElementById(\"rend-select\");\n            mod.rendType=String(parseInt(temp.value));\n            mod.updateShaderFunction();\n            });\n\n         div.appendChild(input);\n   div.appendChild(document.createElement('br'));\n  \n   //\n   // view\n   //   \n   div.appendChild(document.createElement('br'))  ; \n   var btn = document.createElement('button');\n      btn.style.padding = mods.ui.padding;\n      btn.style.margin = 1;\n      var span = document.createElement('span');\n         var text = document.createTextNode('view');\n            span.appendChild(text);\n         btn.appendChild(span);\n      btn.addEventListener('click',function(){\n      mod.windowOpen=true; \n         open_view_window();\n         });\n      div.appendChild(btn);\n}\n\n//\n// local functions\n//\n \n//\n// open_view_window\n//\nfunction open_view_window() {\n    //\n    // globals\n    //\n    var container;\n    var camera, sceneFirstPass, sceneSecondPass, renderer;\n    var containerAxes, cameraAxes , sceneAxes, rendererAxes,axes,sphereO;\n    var rtTexture;\n    var materialSecondPass;\n    var center;\n    var meshSecondPass;\n    var boxGeometry;\n    var gridHelper;\n    var gridHelpersSize=5;\n    var clock;\n    var delta=0;\n    var interval=10;\n    var frameID;\n\n    //\n    // functions\n    //\n   \n    addShaderScripts();\n    open_window();\n   \n    //\n    // open_window\n    //\n    function open_window() \n    {\n      //\n      // open window\n      //\n      win = window.open('');\n      mod.win = win;\n\n      //\n      // load three.js\n      //\n      var script = document.createElement('script');\n      script.type = 'text/javascript';\n      script.onload = init_window;\n      script.src = 'js/three.js/three.min.js';\n      mod.div.appendChild(script);\n    }\n\n      //\n      // add shader scripts to html\n      //\n      function addShaderScripts() \n      {\n\n            /////////////////////////fragmentShaderFirstPass////////////////////////////////////\n\n            var div = document.createElement('script');\n\n            div.id = 'fragmentShaderFirstPass';\n            div.type = 'x-shader/x-fragment';\n\n            div.innerHTML =\n            `\n                  varying vec3 worldSpaceCoords;\n\n                  void main()\n                  {\n                  //The fragment's world space coordinates as fragment output.\n                  gl_FragColor = vec4( worldSpaceCoords.x , worldSpaceCoords.y, worldSpaceCoords.z, 1 );\n                  }\n                  `;\n            \n            //\n            mod.div.appendChild(div);\n            \n            /////////////////////////vertexShaderFirstPass////////////////////////////////////\n            var div = document.createElement('script');\n\n            div.id = 'vertexShaderFirstPass';\n            div.type = 'x-shader/x-vertex';\n\n            div.innerHTML =\n            `\n                  varying vec3 worldSpaceCoords;\n\n                  void main()\n                  {\n                  //Set the world space coordinates of the back faces vertices as output.\n                  worldSpaceCoords = position + vec3(0.5, 0.5, 0.5); //move it from [-0.5;0.5] to [0,1]\n                  gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n                  }\n                  `;\n            \n            //\n            mod.div.appendChild(div);\n            /////////////////////////fragmentShaderSecondPass////////////////////////////////////\n            var div = document.createElement('script');\n\n            div.id = 'fragmentShaderSecondPass';\n            div.type = 'x-shader/x-fragment';\n\n            \n            div.innerHTML=fragmentShaderSecondPass();\n            mod.div.appendChild(div);\n\n            /////////////////////vertexShaderSecondPass///////////////////\n            var div = document.createElement('script');\n\n            div.id = 'vertexShaderSecondPass';\n            div.type = 'x-shader/x-vertex';\n\n            div.innerHTML =\n            `\n                  varying vec3 worldSpaceCoords;\n                  varying vec4 projectedCoords;\n\n\n                  void main()\n                  {\n                  \n                  worldSpaceCoords = (modelMatrix * vec4(position + vec3(0.5, 0.5,0.5), 1.0 )).xyz;\n                  gl_Position = projectionMatrix *  modelViewMatrix * vec4( position, 1.0 );\n                  projectedCoords =  projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n                  }\n                  `;\n            //\n            mod.div.appendChild(div);\n      }\n   \n   //\n   // fragment shader (the one that does all the work)\n   //\n   function fragmentShaderSecondPass()\n   {\n      var txt =\n         `\n            const float PI = 3.1415926535897932384626433832795;\n            #define rendType `+mod.rendType+`\n            varying vec3 worldSpaceCoords;\n            varying vec4 projectedCoords;\n            uniform sampler2D tex;\n            uniform float steps;\n            uniform float alphaCorrection;\n            // uniform float rendType;\n            uniform vec3 cameraPos;\n            // The maximum distance through our rendering volume is sqrt(3).\n            // The maximum number of steps we take to travel a distance of 1 is 512.\n            // ceil( sqrt(3) * 512 ) = 887\n            // This prevents the back of the image from getting cut off when steps=512 & viewing diagonally.\n            const int MAX_STEPS = 887;\n            uniform float xLimit1;\n            uniform float xLimit2;\n            uniform float yLimit1;\n            uniform float yLimit2;\n            uniform float zLimit1;\n            uniform float zLimit2;\n            float orgMin=0.0;\n            float orgMax=1.0;\n            vec3 viewDirection;\n            \n\n            float map(vec3 p)\n            {\n               float X= p.x;\n               float Y= p.y;\n               float Z= p.z;\n\n               return `+mod.str+`;\n            }\n            vec3 simpleLambert (vec3 normal) {\n               vec3 lightDir = vec3(0.2,-0.6,-0.4);   // Light direction\n               vec3 lightDir1 = vec3(0.4, 0.6,-0.4);  // Light direction\n               vec3 lightCol = vec3(0.5,0.5,0.5);     // Light color\n               vec3 _Color=vec3(0.2,0.5,0.8);\n               float lightIntensity = 3.0;\n               float ambient = 0.2;\n               \n               float NdotL = max(dot(normalize(normal), normalize(lightDir)),0.0) * lightIntensity;\n               float NdotL1 = max(dot(normalize(normal), normalize(lightDir1)),0.0) *lightIntensity;\n\n               vec3 c=vec3(0.0,0.0,0.0);\n\n               c.rgb = _Color * lightCol * (NdotL + NdotL1)+ ambient ;\n\n               return c;\n            }\n            vec3 specular (vec3 normal) {\n               vec3 lightDir = vec3(0.2,-0.6,-0.4);   // Light direction\n               vec3 lightDir1 = vec3(0.4, 0.6,-0.4);  // Light direction\n               vec3 lightCol = vec3(0.5,0.5,0.5);     // Light color\n               vec3 _Color=vec3(0.2,0.5,0.8);\n               float lightIntensity=3.0;\n               float ambient = 0.2;\n\n               float _SpecularPower=0.7;\n               float _Gloss=0.7;\n               \n               float NdotL = max(dot(normalize(normal ), normalize(lightDir)),0.0)*lightIntensity;\n               float NdotL1 = max(dot(normalize(normal), normalize(lightDir1)),0.0)*lightIntensity;\n               vec3 c;\n               vec3 camera= cameraPos-0.5;\n\n               float t= dot(normalize(lightDir), normalize( -camera));\n               float tt=(dot(normalize(normal), normalize(-camera)));\n               float s= ( t*_Gloss + tt*_SpecularPower)/lightIntensity;\n\n               float t1= dot(normalize(lightDir1), normalize( -camera));\n               float tt1=(dot(normalize(normal), normalize(-camera)));\n               float s1= ( t1*_Gloss * tt1*_SpecularPower)/2.0;\n\n               // float s = pow( dot(normalize(normal),h), _SpecularPower) * _Gloss;\n               // h.x= (h.x - orgMin) * ((1.0) - (-1.0)) / (orgMax - orgMin) + (-1.0);\n               // h.y= (h.y - orgMin) * ((1.0) - (-1.0)) / (orgMax - orgMin) + (-1.0);\n               // h.z= (h.z - orgMin) * ((1.0) - (-1.0)) / (orgMax - orgMin) + (-1.0);\n               // vec3 h1 =  (lightDir1 + camera)/2.0;\n               // float s1 = pow( dot(normalize(normal)/2.0,h1), _SpecularPower) * _Gloss;\n\n               c.rgb = _Color * lightCol * (NdotL+NdotL1)+s + s1+ ambient;\n               return c;\n            }\n            vec3 frontLight (vec3 normal) {\n               \n                  vec3 camera= cameraPos-0.5;\n                  float t=dot(normalize(normal), normalize(-camera));\n                  vec3 c;\n                  c = vec3(t,t,t);\n                  return c;\n            }\n\n            vec3 ClosestPointOnLine(vec3 start ,vec3 direction ,vec3 vPoint )\n            {\n               vec3 vVector1 = vPoint - start;\n               vec3 vVector2 = normalize(direction);\n            \n               float t = dot(vVector2, vVector1);\n               if (t <= 0.0)\n               {\n                  return start;\n               }\n                  \n               vec3 vVector3 = vVector2 * t;\n            \n               vec3 vClosestPoint = start + vVector3;\n               return vClosestPoint;\n            }\n            vec3 GetClosetPoint( vec3 A, vec3 B, vec3 P, bool segmentClamp)\n            {\n               vec3 AP = P - A;\n               vec3 AB = B - A; \n               float ab2 = AB.x*AB.x + AB.y*AB.y;\n               float apab = AP.x*AB.x + AP.y*AB.y;\n               float t = apab / ab2;\n               if (segmentClamp)\n               {\n                  if (t < 0.0) t = 0.0;\n                  else if (t > 1.0) t = 1.0;\n               }\n               vec3 Closest = A + AB * t;\n               return Closest;\n            }\n            vec3 calcNormal( in vec3 pos )\n            {\n                  // vec2 e = vec2(1.0,-1.0)*0.5773*0.0005;\n                  // return normalize( e.xyy*map( pos + e.xyy ) + \n                  //                         e.yyx*map( pos + e.yyx ) + \n                  //                         e.yxy*map( pos + e.yxy ) + \n                  //                         e.xxx*map( pos + e.xxx ) );\n                  \n                  // vec3 eps = vec3( 0.0005, 0.0, 0.0 );\n                  // vec3 nor = vec3(\n                  //       map(pos+eps.xyy) - map(pos-eps.xyy),\n                  //       map(pos+eps.yxy) - map(pos-eps.yxy),\n                  //       map(pos+eps.yyx) - map(pos-eps.yyx) );\n                  // return normalize(nor);\n\n                  const float eps = 0.01;\n                  vec3 n;\n                  n.x=map(pos + vec3(eps, 0, 0)   ) - map(pos - vec3(eps, 0, 0));\n                  n.y=map(pos + vec3(0, eps, 0)   ) - map(pos - vec3(0, eps, 0));\n                  n.z=map(pos + vec3(0, 0, eps)   ) - map(pos - vec3(0, 0, eps));\n                  //problem with \n                  // n.x=result - map(pos - vec3(eps, 0, 0));\n                  // n.y=result - map(pos - vec3(0, eps, 0));\n                  // n.z=result - map(pos - vec3(0, 0, eps));\n                  return normalize(n);\n                  \n            }\n\n            //Acts like a texture3D using Z slices and trilinear filtering.\n            vec4 sampleAs3DTextureCustom( vec3 texCoord )\n            { \n               float X= (texCoord.x - orgMin) * (xLimit2 - xLimit1) / (orgMax - orgMin) + xLimit1;\n               float Y= (texCoord.y - orgMin) * (yLimit2 - yLimit1) / (orgMax - orgMin) + yLimit1;\n               float Z= (texCoord.z - orgMin) * (zLimit2 - zLimit1) / (orgMax - orgMin) + zLimit1;\n\n               //slice color red\n               vec4 m;\n               m=vec4(0.0,0.0,0.0,0.0);\n\n               float result=`+mod.str+`;\n               if(result>0.0)\n               {\n                  m.a=1.0;\n                  vec3 p=vec3(X,Y,Z);\n                  vec3 n=calcNormal( p );\n\n                  #if rendType==0\n                  //default\n                     {\n                        float tempConst=0.001;\n                        m.rgb=frontLight(n)+tempConst;\n                     }\n                  #elif rendType==1\n                  //xray\n                     {\n                        m=vec4(1.0,1.0,1.0,0.01);\n                     }\n                  #elif rendType==2\n                  //height map\n                     {\n                        m.r=texCoord.z;\n                        m.g=texCoord.z;\n                        m.b=texCoord.z;\n                     }\n                  #elif rendType==3\n                  //depth/height map variable\n                     {\n                        vec3 cp=ClosestPointOnLine(-cameraPos,cameraPos,texCoord);\n                        float d= (distance(cp, normalize(cameraPos)*2.0));\n                        m.r=d;\n                        m.g=d;\n                        m.b=d;\n                     }\n                  #elif rendType==4\n                  //normals\n                     {\n                        m.r= (n.r - (-1.0)) * (1.0 - 0.0) / (1.0 - (-1.0)) + 0.0;\n                        m.g= (n.g - (-1.0)) * (1.0 - 0.0) / (1.0 - (-1.0)) + 0.0;\n                        m.b= (n.b - (-1.0)) * (1.0 - 0.0) / (1.0 - (-1.0)) + 0.0;\n                     }\n                  #elif rendType==5\n                  //fixed lights\n                     {\n                        float tempConst=0.05;\n                        m.rgb=simpleLambert (n)+tempConst;\n                     }\n                  #elif rendType==6\n                  //fixed lights specular\n                     {\n                        float tempConst=0.00;\n                        m.rgb=specular (n)+tempConst;\n                     }\n                  #endif\n                  \n               }\n               return m ;\n            }\n            \n            void main( void ) {\n\n               //Transform the coordinates it from [-1;1] to [0;1]\n               vec2 texc = vec2(((projectedCoords.x / projectedCoords.w) + 1.0 ) / 2.0,\n                           ((projectedCoords.y / projectedCoords.w) + 1.0 ) / 2.0 );\n\n               //The back position is the world space position stored in the texture.\n               vec3 backPos = texture2D(tex, texc).xyz;\n\n               //The front position is the world space position of the second render pass.\n               vec3 frontPos = worldSpaceCoords;\n\n               //The direction from the front position to back position.\n               vec3 dir = backPos - frontPos;\n               \n               float rayLength = length(dir);\n\n               //Calculate how long to increment in each step.\n               float delta = 1.0 / steps;\n\n               //The increment in each direction for each step.\n               vec3 deltaDirection = normalize(dir) * delta;\n\n               viewDirection=normalize(dir);//amira added\n\n               float deltaDirectionLength = length(deltaDirection);\n\n               //Start the ray casting from the front position.\n               vec3 currentPosition = frontPos;\n\n               //The color accumulator.\n               vec4 accumulatedColor = vec4(0.0);\n\n               //The alpha value accumulated so far.\n               float accumulatedAlpha = 0.0;\n\n               //How long has the ray travelled so far.\n               float accumulatedLength = 0.0;\n\n               //If we have twice as many samples, we only need ~1/2 the alpha per sample.\n               //Scaling by 256/10 just happens to give a good value for the alphaCorrection slider.\n               float alphaScaleFactor = 25.6 * delta;\n\n               vec4 colorSample;\n               float alphaSample;\n\n               //Perform the ray marching iterations\n               for(int i = 0; i < MAX_STEPS; i++)\n               {\n                  //Get the voxel intensity value from the 3D texture.\n                  colorSample = sampleAs3DTextureCustom( currentPosition );\n\n                  //Allow the alpha correction customization.\n                  alphaSample = colorSample.a * alphaCorrection;\n\n                  //Applying this effect to both the color and alpha accumulation results in more realistic transparency.\n                  alphaSample *= (1.0 - accumulatedAlpha);\n\n                  //Scaling alpha by the number of steps makes the final color invariant to the step size.\n                  alphaSample *= alphaScaleFactor;\n\n                  //Perform the composition.\n                  accumulatedColor += colorSample * alphaSample;\n\n                  //Store the alpha accumulated so far.\n                  accumulatedAlpha += alphaSample;\n\n                  //Advance the ray.\n                  currentPosition += deltaDirection;\n                  accumulatedLength += deltaDirectionLength;\n\n                  //If the length traversed is more than the ray length, or if the alpha accumulated reaches 1.0 then exit.\n                  if(accumulatedLength >= rayLength || accumulatedAlpha >= 1.0 )\n                     break;\n               }\n\n               gl_FragColor  = accumulatedColor;\n\n            }\n            `;\n      return txt;\n   }\n\n    //\n    // init_window\n    //\n   function init_window() {\n      //\n      // close button\n      //\n      var btn = document.createElement('button');\n         btn.appendChild(document.createTextNode('close'));\n         btn.style.padding = mods.ui.padding;\n         btn.style.margin = 1;\n         btn.addEventListener('click',function(){\n            win.close();\n            mod.win = undefined;\n         });\n         win.document.body.appendChild(btn);\n      //\n      // label text\n      //\n      var text = win.document.createTextNode(' left: pan, right: rotate, scroll: zoom');\n         win.document.body.appendChild(text);\n      //\n      // GL container\n      //\n      win.document.body.appendChild(document.createElement('br')) ;  \n      container = win.document.createElement('div');\n      container.style.overflow = 'hidden';\n      win.document.body.appendChild(container);\n\n      ///////////////////////////////////////////axes////////////////////////////\n      //GL Axes Container\n      // win.document.body.appendChild(document.createElement('br')) ;  \n      containerAxes = win.document.createElement('div');\n      containerAxes.style.overflow = 'hidden';\n      containerAxes.style.position = 'absolute';\n      containerAxes.style.zIndex = 100;\n      containerAxes.style.left = 0;\n      containerAxes.style.bottom = 0;\n      containerAxes.style.margin = 20;\n      win.document.body.appendChild(containerAxes);\n      //\n      //cameraAxes\n      //\n      cameraAxes = new THREE.PerspectiveCamera( 50, 100 / 100, 1, 1000 );\n      cameraAxes.up = new THREE.Vector3(0, 0, 1);\n      //\n      //rendererAxes\n      //\n      rendererAxes = new THREE.WebGLRenderer({ alpha: true } );\n      rendererAxes.setClearColor( 0x000000, 0 );\n      rendererAxes.setSize( 100, 100 );\n      containerAxes.appendChild( rendererAxes.domElement );\n      //\n      //sceneAxes\n      //\n      sceneAxes=new THREE.Scene();\n      axes = new THREE.AxisHelper( 100 );\n      sceneAxes.add( axes );   \n\n      ///////////////////////////////////////////////////////////////////////////////////\n      \n      //\n      //camera\n      //\n      camera = new THREE.PerspectiveCamera( 40, win.innerWidth / win.innerHeight, 0.01, 3000.0 );\n      camera.position.z = 2.0;\n      camera.aspect = win.innerWidth / win.innerHeight;\n      camera.up = new THREE.Vector3(0, 0, 1);\n      camera.position.x = 5;\n      camera.lookAt(new THREE.Vector3(0,0,0));\n      camera.updateProjectionMatrix();\n      center= new THREE.Vector3(0,0,0);\n\n      \n      \n      //\n      //setup textures and scenes\n      //\n      var screenSize = new THREE.Vector2( win.innerWidth, win.innerHeight );\n      rtTexture = new THREE.WebGLRenderTarget( screenSize.x, screenSize.y,\n                                    {  minFilter: THREE.LinearFilter,\n                                       magFilter: THREE.LinearFilter,\n                                       wrapS:  THREE.ClampToEdgeWrapping,\n                                       wrapT:  THREE.ClampToEdgeWrapping,\n                                       format: THREE.RGBAFormat,\n                                       type: THREE.FloatType,\n                                       generateMipmaps: false} );\n\n\n      var materialFirstPass = new THREE.ShaderMaterial( {\n         vertexShader: document.getElementById( 'vertexShaderFirstPass' ).textContent,\n         fragmentShader: document.getElementById( 'fragmentShaderFirstPass' ).textContent,\n         side: THREE.BackSide\n      } );\n\n      var lookAtVector = new THREE.Vector3(0,0, -1);\n      lookAtVector.applyQuaternion(camera.quaternion);\n\n      sceneFirstPass = new THREE.Scene();\n      sceneSecondPass = new THREE.Scene();\n\n      var tempCam=new THREE.Vector3(camera.position.x,camera.position.y,camera.position.z);\n      materialSecondPass = new THREE.ShaderMaterial( {\n         vertexShader: document.getElementById( 'vertexShaderSecondPass' ).textContent,\n         fragmentShader: document.getElementById( 'fragmentShaderSecondPass' ).textContent,\n         side: THREE.FrontSide,\n         uniforms: { tex:  { type: \"t\", value: rtTexture },\n                  steps : {type: \"1f\" , value: mod.steps.value }, \n                  xLimit1 : {type: \"1f\" , value: mod.xLimit1 }, \n                  xLimit2 : {type: \"1f\" , value: mod.xLimit2 }, \n                  yLimit1 : {type: \"1f\" , value: mod.yLimit1 }, \n                  yLimit2 : {type: \"1f\" , value: mod.yLimit2 }, \n                  zLimit1 : {type: \"1f\" , value: mod.zLimit1 }, \n                  zLimit2 : {type: \"1f\" , value: mod.zLimit2 }, \n                  alphaCorrection : {type: \"1f\" , value: mod.alphaCorrection},\n                  cameraPos :{value:  tempCam.normalize()} \n               }\n      });\n\n      //HELPER GRID\n      gridHelper = new THREE.GridHelper( gridHelpersSize, 20 );//SIZE DIVISION\n      var geometry = new THREE.SphereGeometry( 0.1,32,32);\n      var material = new THREE.MeshNormalMaterial();\n      sphereO = new THREE.Mesh( geometry, material );\n\n      var materialX = new THREE.LineBasicMaterial({\n            color: 0xFF0000\n      });\n      var materialY = new THREE.LineBasicMaterial({\n            color: 0x00FF00\n      });\n      \n      var geometryX = new THREE.Geometry();\n      geometryX.vertices.push(\n            new THREE.Vector3( -5, 0, 0 ),\n            new THREE.Vector3(  5, 0, 0 )\n      );\n      var geometryY = new THREE.Geometry();\n      geometryY.vertices.push(\n            new THREE.Vector3( 0, -5, 0 ),\n            new THREE.Vector3( 0,  5, 0 )\n      );\n      \n      var lineX = new THREE.Line( geometryX, materialX );\n      var lineY = new THREE.Line( geometryY, materialY );\n\n      gridHelper.add(lineX);\n      gridHelper.add(lineY);\n      sceneSecondPass.add( gridHelper );\n      // sceneSecondPass.add( sphereO );\n      gridHelper.geometry.rotateX( Math.PI / 2 );\n      \n      updateGridHelper();\n      \n      \n      //\n      //cube renderer\n      //\n      boxGeometry = new THREE.BoxGeometry(1.0, 1.0, 1.0);\n      boxGeometry.doubleSided = true;\n\n      materialSecondPass.transparent =true;\n      var meshFirstPass = new THREE.Mesh( boxGeometry, materialFirstPass );\n      meshSecondPass = new THREE.Mesh( boxGeometry, materialSecondPass );\n\n      sceneFirstPass.add( meshFirstPass );\n      sceneSecondPass.add( meshSecondPass );\n\n      renderer = new THREE.WebGLRenderer();\n      container.appendChild( renderer.domElement );\n      renderer.setSize( win.innerWidth, win.innerHeight );\n\n\n      //\n      // mod viewer\n      //\n\n      //grab the context from your destination canvas\n      var destCtx = mod.canvas.getContext('2d');\n      destCtx.clearRect(0,0,mod.canvas.width,mod.canvas.height);\n      //call its drawImage() function passing it the source canvas directly\n      destCtx.drawImage(container.childNodes[0], 0, 0);\n\n\n      clock=new THREE.Clock();\n      //\n      //controls\n      //\n      var Controls = (function(Controls) {\n         // \"use strict\";\n      \n         // Check for double inclusion\n         if (Controls.addMouseHandler)\n            return Controls;\n      \n         Controls.addMouseHandler = function (domObject, drag, zoomIn, zoomOut) {\n            var startDragX = null,\n               startDragY = null;\n      \n            function mouseWheelHandler(e) {\n               e = window.event || e;\n               var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));\n      \n               if (delta < 0 && zoomOut) {\n                  zoomOut(delta);\n               } else if (zoomIn) {\n                  zoomIn(delta);\n               }\n      \n               e.preventDefault();\n            }\n      \n            function mouseDownHandler(e) {\n               startDragX = e.clientX;\n               startDragY = e.clientY;\n      \n               e.preventDefault();\n            }\n      \n            function mouseMoveHandler(e) {\n               if (startDragX === null || startDragY === null)\n                  return;\n      \n               if (drag)\n                  drag(e.clientX - startDragX, e.clientY - startDragY);\n      \n               startDragX = e.clientX;\n               startDragY = e.clientY;\n      \n               e.preventDefault();\n            }\n      \n            function mouseUpHandler(e) {\n               mouseMoveHandler.call(this, e);\n               startDragX = null;\n               startDragY = null;\n      \n               e.preventDefault();\n            }\n      \n            domObject.addEventListener(\"mousewheel\", mouseWheelHandler);\n            domObject.addEventListener(\"DOMMouseScroll\", mouseWheelHandler);\n            domObject.addEventListener(\"mousedown\", mouseDownHandler);\n            domObject.addEventListener(\"mousemove\", mouseMoveHandler);\n            domObject.addEventListener(\"mouseup\", mouseUpHandler);\n         };\n         return Controls;\n      }(Controls || {}));\n      Controls.addMouseHandler(renderer.domElement, drag, zoomIn, zoomOut);\n      \n\n      //\n      // event handlers\n      //\n      win.addEventListener( 'resize', onWindowResize, false );\n      win.addEventListener('contextmenu',context_menu);\n      \n      render();\n   }\n  \n   //\n   //window resize\n   //\n   function onWindowResize( event ) {\n\n      //TODO: Fix box white edge when window resize\n      renderer.setSize( win.innerWidth, win.innerHeight );\n\n      camera.aspect = win.innerWidth / win.innerHeight;\n      camera.updateProjectionMatrix();\n\n      redraw(false);\n   }\n\n   //\n   //context menu\n   //\n   function context_menu(evt) \n   {\n      evt.preventDefault();\n      evt.stopPropagation();\n      return (false);\n   }\n\n   //\n   // mouse_down\n   //\n   function mouse_down(evt) \n   { \n      evt.preventDefault();\n      evt.stopPropagation();\n      mod.button = evt.button;\n      mod.x = evt.clientX;\n      mod.y = evt.clientY;\n   }\n\n   //\n   // mouse_up\n   //\n   function mouse_up(evt) {\n      mod.button = undefined;\n      mod.x = evt.clientX;\n      mod.y = evt.clientY;\n   }\n\n   //\n   // mouse_move\n   //\n   function mouse_move(evt) \n   {\n      evt.preventDefault();\n      evt.stopPropagation();\n      var dx = evt.clientX-mod.x;\n      var dy = evt.clientY-mod.y;\n      mod.x = evt.clientX;\n      mod.y = evt.clientY;\n      if (mod.button == 0) {\n         mod.x0 += \n            Math.sin(mod.thetaz)*mod.height*dy/win.innerHeight\n            -Math.cos(mod.thetaz)*mod.width*dx/win.innerWidth;\n         mod.y0 += \n            Math.cos(mod.thetaz)*mod.height*dy/win.innerHeight\n            +Math.sin(mod.thetaz)*mod.width*dx/win.innerWidth;\n         camera.position.x = mod.x0+Math.sin(mod.thetaz)*mod.r*Math.sin(mod.thetaxy);\n         camera.position.y = mod.y0+Math.cos(mod.thetaz)*mod.r*Math.sin(mod.thetaxy);\n         camera.position.z = mod.r*Math.cos(mod.thetaxy);\n         camera.position.z = mod.r*Math.cos(mod.thetaxy);\n            camera.up = new THREE.Vector3(Math.sin(mod.thetaz),Math.cos(mod.thetaz),0);\n            camera.lookAt(new THREE.Vector3(mod.x0,mod.y0,0));\n         camera.updateProjectionMatrix();\n         redraw(false);\n      }\n      else if (mod.button == 2) {\n         mod.thetaxy += dy/win.innerHeight;\n         mod.thetaz += dx/win.innerWidth;\n         camera.position.x = mod.x0+Math.sin(mod.thetaz)*mod.r*Math.sin(mod.thetaxy);\n         camera.position.y = mod.y0+Math.cos(mod.thetaz)*mod.r*Math.sin(mod.thetaxy);\n         camera.position.z = mod.r*Math.cos(mod.thetaxy);\n            camera.up = new THREE.Vector3(Math.sin(mod.thetaz),Math.cos(mod.thetaz),0);\n            camera.lookAt(new THREE.Vector3(mod.x0,mod.y0,0));\n         camera.updateProjectionMatrix();\n            renderer.render(scene,camera);\n      }\n   }\n\n   //\n   // mouse_wheel\n   //\n   function mouse_wheel(evt) \n   {\n      evt.preventDefault();\n      evt.stopPropagation();\n      var dy = evt.deltaY/win.innerHeight;\n      mod.r += mod.height*dy;\n      camera.position.x = mod.x0+Math.sin(mod.thetaz)*mod.r*Math.sin(mod.thetaxy);\n      camera.position.y = mod.y0+Math.cos(mod.thetaz)*mod.r*Math.sin(mod.thetaxy);\n      camera.position.z = mod.r*Math.cos(mod.thetaxy);\n      camera.lookAt(new THREE.Vector3(mod.x0,mod.y0,0));\n      camera.updateProjectionMatrix();\n      redraw(false);\n   }\n\n   //\n   //redraw\n   //\n   \n\n   function frame() \n   {\n      if (delta == 5) {\n            delta=0;\n            clearInterval(frameID);\n      } else {\n            delta++; \n            render(true,mod.steps.value*delta/5);\n      }\n   }  \n\n   function redraw(updateUniforms)\n   {\n      if(mod.rendPerformance==1)\n      {\n            if(frameID!=null)\n            {\n                  clearInterval(frameID);\n            }\n            frameID=setInterval(frame, interval);   \n      }else\n      {\n            if(frameID!=null)\n            {\n                  clearInterval(frameID);\n            }\n            render(updateUniforms,mod.steps.value);\n      }\n   }\n   mod.redraw=redraw;\n\n   function updateGridHelper()\n   {\n      //TODO: later move/rotate camera based on changes\n      //update grid helper based on limits\n      gridHelper.geometry.rotateX( - Math.PI / 2 );\n      gridHelper.scale.x=gridHelpersSize/(Math.abs(mod.xLimit2  - mod.xLimit1)*gridHelpersSize/2.0);\n      gridHelper.scale.y=gridHelpersSize/(Math.abs(mod.yLimit2  - mod.yLimit1)*gridHelpersSize/2.0);\n      gridHelper.position.x=( (0.0 - (mod.xLimit1)) * (0.5  - (-0.5)) / (mod.xLimit2 - (mod.xLimit1)) + (-0.5));\n      gridHelper.position.y=( (0.0 - (mod.yLimit1)) * (0.5  - (-0.5)) / (mod.yLimit2 - (mod.yLimit1)) + (-0.5));\n      gridHelper.position.z=( (0.0 - (mod.zLimit1)) * (0.5  - (-0.5)) / (mod.zLimit2 - (mod.zLimit1)) + (-0.5));\n      gridHelper.geometry.rotateX( Math.PI / 2 );\n      \n      sphereO.scale.x=gridHelpersSize/(Math.abs(mod.xLimit2  - mod.xLimit1)*gridHelpersSize/0.5);\n      sphereO.scale.y=gridHelpersSize/(Math.abs(mod.yLimit2  - mod.yLimit1)*gridHelpersSize/0.5);\n      sphereO.scale.z=gridHelpersSize/(Math.abs(mod.zLimit2  - mod.zLimit1)*gridHelpersSize/0.5);\n     \n      sphereO.position.x=( (0.0 - (mod.xLimit1)) * (0.5  - (-0.5)) / (mod.xLimit2 - (mod.xLimit1)) + (-0.5));\n      sphereO.position.y=( (0.0 - (mod.yLimit1)) * (0.5  - (-0.5)) / (mod.yLimit2 - (mod.yLimit1)) + (-0.5));\n      sphereO.position.z=( (0.0 - (mod.zLimit1)) * (0.5  - (-0.5)) / (mod.zLimit2 - (mod.zLimit1)) + (-0.5));\n   }\n\n   //\n   //render\n   //\n   function render(updateUniforms ,resolutionStep) {\n      if(updateUniforms)\n      {\n            \n            materialSecondPass.uniforms.steps.value = resolutionStep;\n            materialSecondPass.uniforms.alphaCorrection.value = mod.alphaCorrection;\n            materialSecondPass.uniforms.xLimit1.value =mod.xLimit1 ;\n            materialSecondPass.uniforms.xLimit2.value =mod.xLimit2 ; \n            materialSecondPass.uniforms.yLimit1.value =mod.yLimit1 ; \n            materialSecondPass.uniforms.yLimit2.value =mod.yLimit2 ; \n            materialSecondPass.uniforms.zLimit1.value =mod.zLimit1 ; \n            materialSecondPass.uniforms.zLimit2.value =mod.zLimit2 ;\n\n\n            //TODO: Find the error with xray and fix it\n            if(mod.rendType=='1')//xray\n            {\n                  materialSecondPass.transparent =false;\n            }else\n            {\n                  materialSecondPass.transparent =true;\n            }\n\n            updateGridHelper();\n      }\n\n      var tempCam=new THREE.Vector3(camera.position.x,camera.position.y,camera.position.z);\n\n      materialSecondPass.uniforms.cameraPos.value=tempCam.normalize();\n      tempCam.normalize();\n      tempCam.addScalar(0.5);\n\n      //Render first pass and store the world space coords of the back face fragments into the texture.\n      renderer.render( sceneFirstPass, camera, rtTexture, true );\n\n      //Render the second pass and perform the volume rendering.\n      renderer.render( sceneSecondPass, camera );\n\n      //render axes camera\n      cameraAxes.position.x=camera.position.x;\n      cameraAxes.position.y=camera.position.y;\n      cameraAxes.position.z=camera.position.z;\n\tcameraAxes.position.sub( center ); \n\tcameraAxes.position.setLength( 300 );\n      cameraAxes.lookAt( sceneAxes.position.clone() );  \n\n      rendererAxes.render( sceneAxes, cameraAxes );\n\n      updateModViewer();\n      \n   }\n\n   //\n   //render to small mod viewer\n   //\n   function updateModViewer()\n   {\n      var w=win.innerWidth;\n      var h=win.innerHeight;\n      if (w > h) {\n         var x0 = 0;\n         var y0 = mod.canvas.height*.5*(1-h/w);\n         var wd = mod.canvas.width;\n         var hd = mod.canvas.width*h/w;\n         }\n       else {\n         var x0 = mod.canvas.width*.5*(1-w/h);\n         var y0 = 0;\n         var wd = mod.canvas.height*w/h;\n         var hd = mod.canvas.height;\n         }\n      var destCtx = mod.canvas.getContext('2d');\n      destCtx.drawImage(container.childNodes[0],x0,y0,wd,hd);\n\n   }\n\n   //\n   //when fuction changes\n   //\n   function updateShaderFunction()\n   {\n      // outputs.messageLog.event('update shader');\n      \n      // outputs.messageLog.event(mod.xLimit1);\n\n      var div = document.getElementById('fragmentShaderSecondPass');\n\n      div.innerHTML=\"\";\n      div.innerHTML =fragmentShaderSecondPass();\n      \n      var tempCam=new THREE.Vector3(camera.position.x,camera.position.y,camera.position.z);\n      // outputs.messageLog.event('update shader1');\n      materialSecondPass = new THREE.ShaderMaterial( {\n         vertexShader: document.getElementById( 'vertexShaderSecondPass' ).textContent,\n         fragmentShader: document.getElementById( 'fragmentShaderSecondPass' ).textContent,\n         side: THREE.FrontSide,\n         uniforms: { tex:  { type: \"t\", value: rtTexture },\n                  steps : {type: \"1f\" , value: mod.steps.value }, \n                  xLimit1 : {type: \"1f\" , value: mod.xLimit1 }, \n                  xLimit2 : {type: \"1f\" , value: mod.xLimit2 }, \n                  yLimit1 : {type: \"1f\" , value: mod.yLimit1 }, \n                  yLimit2 : {type: \"1f\" , value: mod.yLimit2 }, \n                  zLimit1 : {type: \"1f\" , value: mod.zLimit1 }, \n                  zLimit2 : {type: \"1f\" , value: mod.zLimit2 }, \n                  alphaCorrection : {type: \"1f\" , value: mod.alphaCorrection},\n                  cameraPos :{value: tempCam.normalize()}\n               }\n         });\n\n      //new THREE.Vector3(20.0,-60.0,-40.0)\n      meshSecondPass.material=materialSecondPass;\n      meshSecondPass.material.needsUpdate = true;\n      meshSecondPass.material.transparent =true;\n\n      redraw(true);\n\n      //test performance\n      // mod.tend = Date.now();\n      // var dt = mod.tend-mod.tstart;\n      // outputs.messageLog.event(dt/1000);\n\n   }\n   mod.updateShaderFunction=updateShaderFunction;\n      \n      //\n      //controls\n      //\n      function drag(deltaX, deltaY) \n      {\n            var radPerPixel = (Math.PI / 450),\n            deltaPhi = radPerPixel * deltaX,\n            deltaTheta = radPerPixel * deltaY,\n            pos = camera.position.sub(center),\n            radius = pos.length(),\n            theta = Math.acos(pos.z / radius),\n            phi = Math.atan2(pos.y, pos.x);\n\n            // Subtract deltaTheta and deltaPhi\n            theta = Math.min(Math.max(theta - deltaTheta, 0), Math.PI);\n            phi -= deltaPhi;\n\n            // Turn back into Cartesian coordinates\n            pos.x = radius * Math.sin(theta) * Math.cos(phi);\n            pos.y = radius * Math.sin(theta) * Math.sin(phi);\n            pos.z = radius * Math.cos(theta);\n\n            camera.position.add(center);\n            camera.lookAt(center);\n            redraw(false);\n      }\n\n      ///\n      function zoomIn() \n      {\n            camera.position.sub(center).multiplyScalar(0.9).add(center);\n            redraw(false);\n      }\n\n      ///\n      function zoomOut() \n      {\n            camera.position.sub(center).multiplyScalar(1.1).add(center);\n            redraw(false);\n      }\n}\n\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   });\n}());\n\n\n","top":"709.8880770918156","left":"2738.279844505063","inputs":{},"outputs":{}}},"links":["{\"source\":\"{\\\"id\\\":\\\"0.3625970106871924\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.9645985086194264\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape0\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.3625970106871924\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"variables\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.04772797317232935\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"in0\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.04772797317232935\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"out0\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.7152788275346978\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"variables\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.7152788275346978\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.9645985086194264\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape1\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.9645985086194264\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.9645985086194264\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"clear\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.7152788275346978\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.9458395548196141\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.9645985086194264\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.04930175848785401\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape0\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.9458395548196141\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.04930175848785401\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape1\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.3625970106871924\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.5608762029437723\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.04930175848785401\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.40238136387777756\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape0\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.5608762029437723\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.5939459494005885\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.5608762029437723\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.690161531242695\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape0\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.5939459494005885\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.690161531242695\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape1\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.690161531242695\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.690161531242695\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"clear\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.690161531242695\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.19288167008415902\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.19288167008415902\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.40238136387777756\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape1\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.40238136387777756\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.8080126368305371\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.8080126368305371\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.8373334092218472\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.8080126368305371\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.01016844222037161\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.01016844222037161\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.43117078925934216\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}"]}
\ No newline at end of file
+{"modules":{"0.3625970106871924":{"definition":"//\n// frep circle\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep circle'\n//\n// initialization\n//\nvar init = function() {\n   mod.x.value = '0'\n   mod.y.value = '0'\n   mod.radius.value = '1'\n   }\n//\n// inputs\n//\nvar inputs = {\n   variables:{type:'',\n      event:function(evt){\n         for (var p in evt.detail)\n            mod[p].value = evt.detail[p]\n         outputs.variables.event()\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         var x = parseFloat(mod.x.value)\n         var y = parseFloat(mod.y.value)\n         var radius = parseFloat(mod.radius.value)\n         var fn = `((${radius})*(${radius})-((X-(${x}))*(X-(${x}))+(Y-(${y}))*(Y-(${y}))))`\n         var variables = ['X','Y']\n         var limits = [[x-radius,x+radius],[y-radius,y+radius]]\n         var type = 'Magnitude'\n         var shape = {function:fn,variables:variables,limits:limits,type:type}\n         mods.output(mod,'shape',shape)}\n         },\n   variables:{type:'',\n      event:function(){\n         var x = parseFloat(mod.x.value)\n         var y = parseFloat(mod.y.value)\n         var radius = parseFloat(mod.radius.value)\n         var vars = {x:x,y:y,radius:radius}\n         mods.output(mod,'variables',vars)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // x\n   //\n   div.appendChild(document.createTextNode('x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.x = input\n   //\n   // y\n   //\n   div.appendChild(document.createTextNode(' y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.y = input\n   div.appendChild(document.createElement('br'))\n   //\n   // r\n   //\n   div.appendChild(document.createTextNode('radius: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.radius = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.variables.event()\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"331","left":"406","inputs":{},"outputs":{}},"0.8373334092218472":{"definition":"//\n// frep view slice\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep view slice'\n//\n// initialization\n//\nvar init = function() {\n   mod.width.value = '1000'\n   mod.z.value = '0'\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'frep',\n      event:function(evt){\n         mod.fn.value = evt.detail.function\n         view_slice(evt.detail)\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   image:{type:'RGBA',\n      event:function(){\n         var ctx = mod.img.getContext(\"2d\")\n         var img = ctx.getImageData(0,0,mod.img.width,mod.img.height)\n         mods.output(mod,'image',img)\n         }}}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // on-screen drawing canvas\n   //\n   var canvas = document.createElement('canvas')\n      canvas.width = mods.ui.canvas\n      canvas.height = mods.ui.canvas\n      canvas.style.backgroundColor = 'rgb(255,255,255)'\n      div.appendChild(canvas)\n      mod.canvas = canvas\n   div.appendChild(document.createElement('br'))\n   //\n   // off-screen image canvas\n   //\n   var canvas = document.createElement('canvas')\n      mod.img = canvas\n   //\n   // x\n   //\n   div.appendChild(document.createTextNode('x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      input.addEventListener('input',function(){\n         mod.y.value = ''\n         mod.z.value = ''\n         })\n      div.appendChild(input)\n      mod.x = input\n   //\n   // y\n   //\n   div.appendChild(document.createTextNode(' y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      input.addEventListener('input',function(){\n         mod.x.value = ''\n         mod.z.value = ''\n         })\n      div.appendChild(input)\n      mod.y = input\n   //\n   // z\n   //\n   div.appendChild(document.createTextNode(' z: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      input.addEventListener('input',function(){\n         mod.x.value = ''\n         mod.y.value = ''\n         })\n      div.appendChild(input)\n      mod.z = input\n   div.appendChild(document.createElement('br'))\n   //\n   // width\n   //\n   div.appendChild(document.createTextNode('width: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      input.addEventListener('input',function(){\n         mod.height.value = ''\n         })\n      div.appendChild(input)\n      mod.width = input\n   //\n   // height\n   //\n   div.appendChild(document.createTextNode(' height: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      input.addEventListener('input',function(){\n         mod.width.value = ''\n         })\n      div.appendChild(input)\n      mod.height = input\n   div.appendChild(document.createElement('br'))\n   //\n   // function\n   //\n   div.appendChild(document.createTextNode('function: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn = input\n   div.appendChild(document.createElement('br'))\n   //\n   // view button\n   //\n   div.appendChild(document.createTextNode(' '))\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('view'))\n      btn.addEventListener('click',function(){\n         mod.win = window.open('')\n         mod.win.document.body.style.overflow = 'hidden'\n         mod.win.document.body.style.border = 0\n         mod.win.document.body.style.padding = 0\n         mod.win.document.body.style.margin = 0\n         mod.win.addEventListener('unload',function() {\n            mod.win = null\n            })\n         var canvas = document.createElement('canvas')\n            canvas.setAttribute('id',mod.div.id+'canvas')\n            mod.win.document.body.appendChild(canvas)\n         var ctx = canvas.getContext(\"2d\")\n         canvas.width = window.innerWidth\n         canvas.height = window.innerWidth\n         var h = mod.img.height\n         var w = mod.img.width\n         if (w > h) {\n            var wd = canvas.width\n            var hd = canvas.width*h/w\n            }\n         else {\n            var wd = canvas.height*w/h\n            var hd = canvas.height\n            }\n         ctx.fillStyle = '#dddddd'\n         ctx.fillRect(0,0,canvas.width,canvas.height)\n         ctx.drawImage(mod.img,0,0,wd,hd)\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n// view_slice\n//\nfunction view_slice(shape) {   \n   var fn = shape.function\n   var vars = shape.variables\n   var limits = shape.limits\n   var type = shape.type\n   var x = parseFloat(mod.x.value)\n   var y = parseFloat(mod.y.value)\n   var z = parseFloat(mod.z.value)\n   var w = parseInt(mod.width.value)\n   var h = parseInt(mod.height.value)\n   if (vars.length == 2) {\n      var xvar = vars[0]\n      var xlimits = limits[0]\n      var yvar = vars[1]\n      var ylimits = limits[1]\n      var zvar = ''\n      var zval = 0\n      }\n   else if (!isNaN(x)) {\n      var xvar = vars[1]\n      var xlimits = limits[1]\n      var yvar = vars[2]\n      var ylimits = limits[2]\n      var zvar = vars[0]\n      var zval = x\n      }\n   else if (!isNaN(y)) {\n      var xvar = vars[0]\n      var xlimits = limits[0]\n      var yvar = vars[2]\n      var ylimits = limits[2]\n      var zvar = vars[1]\n      var zval = y\n      }\n   else if (!isNaN(z)) {\n      var xvar = vars[0]\n      var xlimits = limits[0]\n      var yvar = vars[1]\n      var ylimits = limits[1]\n      var zvar = vars[2]\n      var zval = z\n      }\n   if (!isNaN(w))\n      h = Math.floor(w*(ylimits[1]-ylimits[0])/(xlimits[1]-xlimits[0]))\n   else\n      w = Math.floor(h*(xlimits[1]-xlimits[0])/(ylimits[1]-ylimits[0]))\n   mod.img.height = h\n   mod.img.width = w\n   var blob = new Blob(['('+worker.toString()+'())'])\n   var url = window.URL.createObjectURL(blob)\n   var webworker = new Worker(url)\n   webworker.addEventListener('message',function(evt) {\n      window.URL.revokeObjectURL(url)\n      var h = mod.img.height\n      var w = mod.img.width\n      var buf = new Uint8ClampedArray(evt.data.buffer)\n      var imgdata = new ImageData(buf,w,h)\n      var ctx = mod.img.getContext(\"2d\")\n      ctx.putImageData(imgdata,0,0)\n      if (w > h) {\n         var x0 = 0\n         var y0 = mod.canvas.height*.5*(1-h/w)\n         var wd = mod.canvas.width\n         var hd = mod.canvas.width*h/w\n         }\n      else {\n         var x0 = mod.canvas.width*.5*(1-w/h)\n         var y0 = 0\n         var wd = mod.canvas.height*w/h\n         var hd = mod.canvas.height\n         }\n      var ctx = mod.canvas.getContext(\"2d\")\n      ctx.fillStyle = '#dddddd'\n      ctx.fillRect(0,0,mod.canvas.width,mod.canvas.height)\n      ctx.drawImage(mod.img,x0,y0,wd,hd)\n      if (mod.win != null) {\n         var canvas = mod.win.document.getElementById(mod.div.id+'canvas')\n         var ctx = canvas.getContext(\"2d\")\n         canvas.width = window.innerWidth\n         canvas.height = window.innerWidth\n         var h = mod.img.height\n         var w = mod.img.width\n         if (w > h) {\n            var wd = canvas.width\n            var hd = canvas.width*h/w\n            }\n         else {\n            var wd = canvas.height*w/h\n            var hd = canvas.height\n            }\n         ctx.fillStyle = '#dddddd'\n         ctx.fillRect(0,0,canvas.width,canvas.height)\n         ctx.drawImage(mod.img,0,0,wd,hd)\n         }\n      webworker.terminate()\n      outputs.image.event()\n      })\n   var ctx = mod.canvas.getContext(\"2d\")\n   ctx.fillStyle = '#dddddd'\n   ctx.fillRect(0,0,mod.canvas.width,mod.canvas.height)\n   var ctx = mod.img.getContext(\"2d\")\n   ctx.fillStyle = '#dddddd'\n   ctx.fillRect(0,0,mod.img.width,mod.img.height)\n   var img = ctx.getImageData(0,0,mod.img.width,mod.img.height)\n   webworker.postMessage({\n      height:img.height,width:img.width,\n      xvar:xvar,yvar:yvar,zvar:zvar,zval:zval,\n      xlimits:xlimits,ylimits:ylimits,\n      function:fn,\n      buffer:img.data.buffer},\n      [img.data.buffer])\n   }\n//\n// worker\n//\nfunction worker() {\n   self.addEventListener('message',function(evt) {\n      var h = evt.data.height\n      var w = evt.data.width\n      var xvar = evt.data.xvar\n      var yvar = evt.data.yvar\n      var zvar = evt.data.zvar\n      var zval = evt.data.zval\n      var xlimits = evt.data.xlimits\n      var ylimits = evt.data.ylimits\n      var buf = new Uint8ClampedArray(evt.data.buffer)\n      var f = new Function(xvar,yvar,zvar,'return ('+evt.data.function+')')\n      var x,y,v\n      for (var row = 0; row < h; ++row) {\n         y = ylimits[0]+(ylimits[1]-ylimits[0])*row/(h-1)\n         for (var col = 0; col < w; ++col) {\n            x = xlimits[0]+(xlimits[1]-xlimits[0])*col/(w-1)\n            v = (f(x,y,zval) >= 0) ? 255 : 0\n            buf[(h-1-row)*w*4+col*4+0] = v\n            buf[(h-1-row)*w*4+col*4+1] = v\n            buf[(h-1-row)*w*4+col*4+2] = v\n            buf[(h-1-row)*w*4+col*4+3] = 255\n            }\n         }\n      self.postMessage({buffer:buf.buffer},[buf.buffer])\n      })\n   }\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"292","left":"2803","inputs":{},"outputs":{}},"0.7152788275346978":{"definition":"//\n// frep circle\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep circle'\n//\n// initialization\n//\nvar init = function() {\n   mod.x.value = '0.4'\n   mod.y.value = '0.4'\n   mod.radius.value = '0.16666666666666666'\n   }\n//\n// inputs\n//\nvar inputs = {\n   variables:{type:'',\n      event:function(evt){\n         for (var p in evt.detail)\n            mod[p].value = evt.detail[p]\n         outputs.variables.event()\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         var x = parseFloat(mod.x.value)\n         var y = parseFloat(mod.y.value)\n         var radius = parseFloat(mod.radius.value)\n         var fn = `((${radius})*(${radius})-((X-(${x}))*(X-(${x}))+(Y-(${y}))*(Y-(${y}))))`\n         var variables = ['X','Y']\n         var limits = [[x-radius,x+radius],[y-radius,y+radius]]\n         var type = 'Magnitude'\n         var shape = {function:fn,variables:variables,limits:limits,type:type}\n         mods.output(mod,'shape',shape)}\n         },\n   variables:{type:'',\n      event:function(){\n         var x = parseFloat(mod.x.value)\n         var y = parseFloat(mod.y.value)\n         var radius = parseFloat(mod.radius.value)\n         var vars = {x:x,y:y,radius:radius}\n         mods.output(mod,'variables',vars)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // x\n   //\n   div.appendChild(document.createTextNode('x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.x = input\n   //\n   // y\n   //\n   div.appendChild(document.createTextNode(' y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.y = input\n   div.appendChild(document.createElement('br'))\n   //\n   // r\n   //\n   div.appendChild(document.createTextNode('radius: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.radius = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.variables.event()\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"661","left":"793","inputs":{},"outputs":{}},"0.04772797317232935":{"definition":"//\n// construct object\n//\n// Neil Gershenfeld \n// (c) Massachusetts Institute of Technology 2018\n// \n// This work may be reproduced, modified, distributed, performed, and \n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is \n// provided as is; no warranty is provided, and users accept all \n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'construct object'\n//\n// initialization\n//\nvar init = function() {\n   mod.in0.value = '{\"x\":0,\"y\":0,\"radius\":1}'\n   mod.in1.value = '{}'\n   mod.out0.value = '{x:.4*in0.radius,y:.4*in0.radius,radius:in0.radius/6}'\n   mod.out1.value = '{}'\n   }\n//\n// inputs\n//\nvar inputs = {\n   in0:{type:'',label:'input 0',\n      event:function(evt) {\n         mod.in0.value = JSON.stringify(evt.detail)\n         construct_output()\n         }},\n   in1:{type:'',label:'input 1',\n      event:function(evt) {\n         mod.in1.value = JSON.stringify(evt.detail)\n         construct_output()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   out0:{type:'',label:'output 0',\n      event:function(arg){\n         mods.output(mod,'out0',arg)\n         }},\n   out1:{type:'',label:'output 1',\n      event:function(arg){\n         mods.output(mod,'out1',arg)\n         }}}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // inputs\n   //\n   div.appendChild(document.createTextNode('input 0:'))\n   div.appendChild(document.createElement('br'))\n   var text = document.createElement('textarea')\n      text.setAttribute('rows',1)\n      text.setAttribute('cols',mods.ui.cols)\n      div.appendChild(text)\n      mod.in0 = text\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('input 1:'))\n   div.appendChild(document.createElement('br'))\n   var text = document.createElement('textarea')\n      text.setAttribute('rows',1)\n      text.setAttribute('cols',mods.ui.cols)\n      div.appendChild(text)\n      mod.in1 = text\n   div.appendChild(document.createElement('br'))\n   //\n   // outputs\n   //\n   div.appendChild(document.createTextNode('output 0:'))\n   div.appendChild(document.createElement('br'))\n   var text = document.createElement('textarea')\n      text.setAttribute('rows',1)\n      text.setAttribute('cols',mods.ui.cols)\n      div.appendChild(text)\n      mod.out0 = text\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('output 1:'))\n   div.appendChild(document.createElement('br'))\n   var text = document.createElement('textarea')\n      text.setAttribute('rows',1)\n      text.setAttribute('cols',mods.ui.cols)\n      div.appendChild(text)\n      mod.out1 = text\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         construct_output()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\nfunction construct_output() {\n   var in0 = JSON.parse(mod.in0.value)\n   var in1 = JSON.parse(mod.in1.value)\n   eval('out0 ='+mod.out0.value)\n   eval('out1 ='+mod.out1.value)\n   outputs.out0.event(out0)\n   outputs.out1.event(out1)\n   }\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"613","left":"339","inputs":{},"outputs":{}},"0.9645985086194264":{"definition":"//\n// frep subtract\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2017\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep subtract'\n//\n// initialization\n//\nvar init = function() {\n   mod.shape0 = null\n   mod.shape1 = null\n   mod.fn0.value = ''\n   mod.fn1.value = ''\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape0:{type:'',label:'shape 0',\n      event:function(evt){\n         mod.shape0 = evt.detail\n         mod.fn0.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   shape1:{type:'',label:'shape 1',\n      event:function(evt){\n         mod.shape1 = evt.detail\n         mod.fn1.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   clear:{type:'',\n      event:function(evt){\n         mod.shape0 = null\n         mod.shape1 = null\n         mod.fn0.value = ''\n         mod.fn1.value = ''\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         if ((mod.shape0 != null) && (mod.shape1 != null)) {\n            var fn = `Math.min(${mod.shape0.function},-(${mod.shape1.function}))`\n            var variables = mod.shape0.variables\n            var type = mod.shape0.type        \n            var limits = []\n            for (var v = 0; v < mod.shape0.limits.length; ++v)\n               limits[v] = [mod.shape0.limits[v][0],mod.shape0.limits[v][1]]\n            var shape = {function:fn,variables:variables,limits:limits,type:type}\n            mods.output(mod,'shape',shape)}\n            }\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // function 0\n   //\n   div.appendChild(document.createTextNode('function 0: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn0 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // function 1\n   //\n   div.appendChild(document.createTextNode('function 1: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn1 = input\n   div.appendChild(document.createElement('br'))\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"345","left":"800","inputs":{},"outputs":{}},"0.9458395548196141":{"definition":"//\n// frep reflect\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep reflect'\n//\n// initialization\n//\nvar init = function() {\n   mod.origin0.value = '0'\n   mod.origin1.value = '0'\n   mod.x.checked = true\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'',\n      event:function(evt){\n         mod.shape = evt.detail\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         var fn = mod.shape.function\n         var variables = mod.shape.variables\n         var type = mod.shape.type        \n         var origin0 = parseFloat(mod.origin0.value)\n         var origin1 = parseFloat(mod.origin1.value)\n         var limits = []\n         for (var v = 0; v < mod.shape.limits.length; ++v) {\n            limits[v] = []\n            limits[v][0] = mod.shape.limits[v][0]\n            limits[v][1] = mod.shape.limits[v][1]\n            }\n         if (mod.x.checked) {\n            var xvar = variables[0]\n            var re = new RegExp(xvar,'g')\n            fn = fn.replace(re,`(${2*origin0}-(${xvar}))`)\n            var dx = mod.shape.limits[0][1]-mod.shape.limits[0][0]\n            var dl = mod.shape.limits[0][0]-origin0\n            limits[0][0] = origin0-(dl+dx)\n            limits[0][1] = origin0-dl\n            }\n         else if (mod.y.checked) {\n            var yvar = variables[1]\n            var re = new RegExp(yvar,'g')\n            fn = fn.replace(re,`(${2*origin0}-(${yvar}))`)\n            var dy = mod.shape.limits[1][1]-mod.shape.limits[1][0]\n            var dl = mod.shape.limits[1][0]-origin0\n            limits[1][0] = origin0-(dl+dy)\n            limits[1][1] = origin0-dl\n            }\n         else if (mod.z.checked) {\n            var zvar = variables[2]\n            var re = new RegExp(zvar,'g')\n            fn = fn.replace(re,`(${2*origin0}-(${zvar}))`)\n            var dz = mod.shape.limits[2][1]-mod.shape.limits[2][0]\n            var dl = mod.shape.limits[2][0]-origin0\n            limits[2][0] = origin0-(dl+dz)\n            limits[2][1] = origin0-dl\n            }\n         else if (mod.xy.checked) {\n            var xvar = variables[0]\n            var yvar = variables[1]\n            var xre = new RegExp(xvar,'g')\n            var yre = new RegExp(yvar,'g')\n            fn = fn.replace(xre,'TEMP')\n            fn = fn.replace(yre,`((${origin1})+(${xvar})-(${origin0}))`)\n            fn = fn.replace(/TEMP/g,`((${origin0})+(${yvar})-(${origin1}))`)\n            var dx = mod.shape.limits[0][1]-mod.shape.limits[0][0]\n            var dy = mod.shape.limits[1][1]-mod.shape.limits[1][0]\n            var dxl = mod.shape.limits[0][0]-origin0\n            var dyl = mod.shape.limits[1][0]-origin1\n            limits[0][0] = origin0+dyl\n            limits[0][1] = origin0+dyl+dy\n            limits[1][0] = origin1+dxl\n            limits[1][1] = origin1+dxl+dx\n            }\n         else if (mod.xz.checked) {\n            var xvar = variables[0]\n            var zvar = variables[2]\n            var xre = new RegExp(xvar,'g')\n            var zre = new RegExp(zvar,'g')\n            fn = fn.replace(xre,'TEMP')\n            fn = fn.replace(zre,`((${origin1})+(${xvar})-(${origin0}))`)\n            fn = fn.replace(/TEMP/g,`((${origin0})+(${zvar})-(${origin1}))`)\n            var dx = mod.shape.limits[0][1]-mod.shape.limits[0][0]\n            var dz = mod.shape.limits[2][1]-mod.shape.limits[2][0]\n            var dxl = mod.shape.limits[0][0]-origin0\n            var dzl = mod.shape.limits[2][0]-origin1\n            limits[0][0] = origin0+dzl\n            limits[0][1] = origin0+dzl+dz\n            limits[2][0] = origin1+dxl\n            limits[2][1] = origin1+dxl+dx\n            }\n         else if (mod.yz.checked) {\n            var yvar = variables[1]\n            var zvar = variables[2]\n            var yre = new RegExp(yvar,'g')\n            var zre = new RegExp(zvar,'g')\n            fn = fn.replace(yre,'TEMP')\n            fn = fn.replace(zre,`((${origin1})+(${yvar})-(${origin0}))`)\n            fn = fn.replace(/TEMP/g,`((${origin0})+(${zvar})-(${origin1}))`)\n            var dy = mod.shape.limits[1][1]-mod.shape.limits[1][0]\n            var dz = mod.shape.limits[2][1]-mod.shape.limits[2][0]\n            var dyl = mod.shape.limits[1][0]-origin0\n            var dzl = mod.shape.limits[2][0]-origin1\n            limits[1][0] = origin0+dzl\n            limits[1][1] = origin0+dzl+dz\n            limits[2][0] = origin1+dyl\n            limits[2][1] = origin1+dyl+dy\n            }\n         var shape = {function:fn,variables:variables,limits:limits,type:type}\n         mods.output(mod,'shape',shape)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // axis\n   //\n   div.appendChild(document.createTextNode('axis: '))\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('x'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      input.id = mod.div.id+'x'\n      div.appendChild(input)\n      mod.x = input\n   div.appendChild(document.createTextNode(' y'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      input.id = mod.div.id+'y'\n      div.appendChild(input)\n      mod.y = input\n   div.appendChild(document.createTextNode(' z'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      input.id = mod.div.id+'z'\n      div.appendChild(input)\n      mod.z = input\n   div.appendChild(document.createElement('br'))\n   //\n   // origin 0\n   //\n   div.appendChild(document.createTextNode('origin 0: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.origin0 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // axis\n   //\n   div.appendChild(document.createTextNode('xy'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      input.id = mod.div.id+'xy'\n      div.appendChild(input)\n      mod.xy = input\n   div.appendChild(document.createTextNode(' xz'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      input.id = mod.div.id+'xz'\n      div.appendChild(input)\n      mod.xz = input\n   div.appendChild(document.createTextNode(' yz'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      input.id = mod.div.id+'yz'\n      div.appendChild(input)\n      mod.yz = input\n   div.appendChild(document.createElement('br'))\n   //\n   // origin 1\n   //\n   div.appendChild(document.createTextNode('origin 1: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.origin1 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"660","left":"1160","inputs":{},"outputs":{}},"0.04930175848785401":{"definition":"//\n// frep subtract\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2017\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep subtract'\n//\n// initialization\n//\nvar init = function() {\n   mod.shape0 = null\n   mod.shape1 = null\n   mod.fn0.value = 'Math.min(((1)*(1)-((X-(0))*(X-(0))+(Y-(0))*(Y-(0)))),-(((0.16666666666666666)*(0.16666666666666666)-((X-(0.4))*(X-(0.4))+(Y-(0.4))*(Y-(0.4))))))'\n   mod.fn1.value = '((0.16666666666666666)*(0.16666666666666666)-(((0-(X))-(0.4))*((0-(X))-(0.4))+(Y-(0.4))*(Y-(0.4))))'\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape0:{type:'',label:'shape 0',\n      event:function(evt){\n         mod.shape0 = evt.detail\n         mod.fn0.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   shape1:{type:'',label:'shape 1',\n      event:function(evt){\n         mod.shape1 = evt.detail\n         mod.fn1.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   clear:{type:'',\n      event:function(evt){\n         mod.shape0 = null\n         mod.shape1 = null\n         mod.fn0.value = ''\n         mod.fn1.value = ''\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         if ((mod.shape0 != null) && (mod.shape1 != null)) {\n            var fn = `Math.min(${mod.shape0.function},-(${mod.shape1.function}))`\n            var variables = mod.shape0.variables\n            var type = mod.shape0.type        \n            var limits = []\n            for (var v = 0; v < mod.shape0.limits.length; ++v)\n               limits[v] = [mod.shape0.limits[v][0],mod.shape0.limits[v][1]]\n            var shape = {function:fn,variables:variables,limits:limits,type:type}\n            mods.output(mod,'shape',shape)}\n            }\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // function 0\n   //\n   div.appendChild(document.createTextNode('function 0: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn0 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // function 1\n   //\n   div.appendChild(document.createTextNode('function 1: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn1 = input\n   div.appendChild(document.createElement('br'))\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"342","left":"1160","inputs":{},"outputs":{}},"0.5608762029437723":{"definition":"//\n// frep scale\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep scale'\n//\n// initialization\n//\nvar init = function() {\n   mod.ox.value = '0'\n   mod.oy.value = '0'\n   mod.oz.value = ''\n   mod.sx.value = '.7'\n   mod.sy.value = '.7'\n   mod.sz.value = ''\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'',\n      event:function(evt){\n         mod.shape = evt.detail\n         outputs.shape.event()\n         }},\n   variables:{type:'',\n      event:function(evt){\n         for (var p in evt.detail)\n            mod[p].value = evt.detail[p]\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         var fn = mod.shape.function\n         var variables = mod.shape.variables\n         var type = mod.shape.type        \n         var limits = []\n         for (var v = 0; v < mod.shape.limits.length; ++v) {\n            limits[v] = []\n            limits[v][0] = mod.shape.limits[v][0]\n            limits[v][1] = mod.shape.limits[v][1]\n            }\n         if (mod.ox.value != '') {\n            var ox = parseFloat(mod.ox.value)\n            var sx = parseFloat(mod.sx.value)\n            var xvar = variables[0]\n            var re = new RegExp(xvar,'g')\n            fn = fn.replace(re,`((${ox})+(${xvar}-(${ox}))/(${sx}))`)\n            limits[0][0] = ox+(limits[0][0]-ox)*sx\n            limits[0][1] = ox+(limits[0][1]-ox)*sx\n            }\n         if (mod.oy.value != '') {\n            var oy = parseFloat(mod.oy.value)\n            var sy = parseFloat(mod.sy.value)\n            var yvar = variables[1]\n            var re = new RegExp(yvar,'g')\n            fn = fn.replace(re,`((${oy})+(${yvar}-(${oy}))/(${sy}))`)\n            limits[1][0] = oy+(limits[1][0]-oy)*sy\n            limits[1][1] = oy+(limits[1][1]-oy)*sy\n            }\n         if (mod.oz.value != '') {\n            var oz = parseFloat(mod.oz.value)\n            var sz = parseFloat(mod.sz.value)\n            var zvar = variables[2]\n            var re = new RegExp(zvar,'g')\n            fn = fn.replace(re,`((${oz})+(${zvar}-(${oz}))/(${sz}))`)\n            limits[2][0] = oz+(limits[2][0]-oz)*sz\n            limits[2][1] = oz+(limits[2][1]-oz)*sz\n            }\n         var shape = {function:fn,variables:variables,limits:limits,type:type}\n         mods.output(mod,'shape',shape)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // origin\n   //\n   div.appendChild(document.createTextNode('origin x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.ox = input\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.oy = input\n   div.appendChild(document.createTextNode(' z: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.oz = input\n   div.appendChild(document.createElement('br'))\n   //\n   // scale\n   //\n   div.appendChild(document.createTextNode('scale x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.sx = input\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.sy = input\n   div.appendChild(document.createTextNode(' z: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.sz = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"687","left":"1571","inputs":{},"outputs":{}},"0.40238136387777756":{"definition":"//\n// frep subtract\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2017\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep subtract'\n//\n// initialization\n//\nvar init = function() {\n   mod.shape0 = null\n   mod.shape1 = null\n   mod.fn0.value = 'Math.min(Math.min(((1)*(1)-((X-(0))*(X-(0))+(Y-(0))*(Y-(0)))),-(((0.16666666666666666)*(0.16666666666666666)-((X-(0.4))*(X-(0.4))+(Y-(0.4))*(Y-(0.4)))))),-(((0.16666666666666666)*(0.16666666666666666)-(((0-(X))-(0.4))*((0-(X))-(0.4))+(Y-(0.4))*(Y-(0.4))))))'\n   mod.fn1.value = 'Math.min(((0)-Y),(Math.min(((1)*(1)-((((0)+(X-(0))/(0.7))-(0))*(((0)+(X-(0))/(0.7))-(0))+(((0)+(Y-(0))/(0.7))-(0))*(((0)+(Y-(0))/(0.7))-(0)))),-(((1)*(1)-((((0)+(((0)+(X-(0))/(0.75))-(0))/(0.7))-(0))*(((0)+(((0)+(X-(0))/(0.75))-(0))/(0.7))-(0))+(((0)+(((0)+(Y-(0))/(0.75))-(0))/(0.7))-(0))*(((0)+(((0)+(Y-(0))/(0.75))-(0))/(0.7))-(0))))))))'\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape0:{type:'',label:'shape 0',\n      event:function(evt){\n         mod.shape0 = evt.detail\n         mod.fn0.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   shape1:{type:'',label:'shape 1',\n      event:function(evt){\n         mod.shape1 = evt.detail\n         mod.fn1.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   clear:{type:'',\n      event:function(evt){\n         mod.shape0 = null\n         mod.shape1 = null\n         mod.fn0.value = ''\n         mod.fn1.value = ''\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         if ((mod.shape0 != null) && (mod.shape1 != null)) {\n            var fn = `Math.min(${mod.shape0.function},-(${mod.shape1.function}))`\n            var variables = mod.shape0.variables\n            var type = mod.shape0.type        \n            var limits = []\n            for (var v = 0; v < mod.shape0.limits.length; ++v)\n               limits[v] = [mod.shape0.limits[v][0],mod.shape0.limits[v][1]]\n            var shape = {function:fn,variables:variables,limits:limits,type:type}\n            mods.output(mod,'shape',shape)}\n            }\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // function 0\n   //\n   div.appendChild(document.createTextNode('function 0: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn0 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // function 1\n   //\n   div.appendChild(document.createTextNode('function 1: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn1 = input\n   div.appendChild(document.createElement('br'))\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"332","left":"1519","inputs":{},"outputs":{}},"0.5939459494005885":{"definition":"//\n// frep scale\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep scale'\n//\n// initialization\n//\nvar init = function() {\n   mod.ox.value = '0'\n   mod.oy.value = '0'\n   mod.oz.value = ''\n   mod.sx.value = '.75'\n   mod.sy.value = '.75'\n   mod.sz.value = ''\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'',\n      event:function(evt){\n         mod.shape = evt.detail\n         outputs.shape.event()\n         }},\n   variables:{type:'',\n      event:function(evt){\n         for (var p in evt.detail)\n            mod[p].value = evt.detail[p]\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         var fn = mod.shape.function\n         var variables = mod.shape.variables\n         var type = mod.shape.type        \n         var limits = []\n         for (var v = 0; v < mod.shape.limits.length; ++v) {\n            limits[v] = []\n            limits[v][0] = mod.shape.limits[v][0]\n            limits[v][1] = mod.shape.limits[v][1]\n            }\n         if (mod.ox.value != '') {\n            var ox = parseFloat(mod.ox.value)\n            var sx = parseFloat(mod.sx.value)\n            var xvar = variables[0]\n            var re = new RegExp(xvar,'g')\n            fn = fn.replace(re,`((${ox})+(${xvar}-(${ox}))/(${sx}))`)\n            limits[0][0] = ox+(limits[0][0]-ox)*sx\n            limits[0][1] = ox+(limits[0][1]-ox)*sx\n            }\n         if (mod.oy.value != '') {\n            var oy = parseFloat(mod.oy.value)\n            var sy = parseFloat(mod.sy.value)\n            var yvar = variables[1]\n            var re = new RegExp(yvar,'g')\n            fn = fn.replace(re,`((${oy})+(${yvar}-(${oy}))/(${sy}))`)\n            limits[1][0] = oy+(limits[1][0]-oy)*sy\n            limits[1][1] = oy+(limits[1][1]-oy)*sy\n            }\n         if (mod.oz.value != '') {\n            var oz = parseFloat(mod.oz.value)\n            var sz = parseFloat(mod.sz.value)\n            var zvar = variables[2]\n            var re = new RegExp(zvar,'g')\n            fn = fn.replace(re,`((${oz})+(${zvar}-(${oz}))/(${sz}))`)\n            limits[2][0] = oz+(limits[2][0]-oz)*sz\n            limits[2][1] = oz+(limits[2][1]-oz)*sz\n            }\n         var shape = {function:fn,variables:variables,limits:limits,type:type}\n         mods.output(mod,'shape',shape)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // origin\n   //\n   div.appendChild(document.createTextNode('origin x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.ox = input\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.oy = input\n   div.appendChild(document.createTextNode(' z: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.oz = input\n   div.appendChild(document.createElement('br'))\n   //\n   // scale\n   //\n   div.appendChild(document.createTextNode('scale x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.sx = input\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.sy = input\n   div.appendChild(document.createTextNode(' z: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 6\n      div.appendChild(input)\n      mod.sz = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"744","left":"1976","inputs":{},"outputs":{}},"0.690161531242695":{"definition":"//\n// frep subtract\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2017\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep subtract'\n//\n// initialization\n//\nvar init = function() {\n   mod.shape0 = null\n   mod.shape1 = null\n   mod.fn0.value = ''\n   mod.fn1.value = ''\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape0:{type:'',label:'shape 0',\n      event:function(evt){\n         mod.shape0 = evt.detail\n         mod.fn0.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   shape1:{type:'',label:'shape 1',\n      event:function(evt){\n         mod.shape1 = evt.detail\n         mod.fn1.value = evt.detail.function\n         outputs.shape.event()\n         }},\n   clear:{type:'',\n      event:function(evt){\n         mod.shape0 = null\n         mod.shape1 = null\n         mod.fn0.value = ''\n         mod.fn1.value = ''\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         if ((mod.shape0 != null) && (mod.shape1 != null)) {\n            var fn = `Math.min(${mod.shape0.function},-(${mod.shape1.function}))`\n            var variables = mod.shape0.variables\n            var type = mod.shape0.type        \n            var limits = []\n            for (var v = 0; v < mod.shape0.limits.length; ++v)\n               limits[v] = [mod.shape0.limits[v][0],mod.shape0.limits[v][1]]\n            var shape = {function:fn,variables:variables,limits:limits,type:type}\n            mods.output(mod,'shape',shape)}\n            }\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // function 0\n   //\n   div.appendChild(document.createTextNode('function 0: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn0 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // function 1\n   //\n   div.appendChild(document.createTextNode('function 1: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn1 = input\n   div.appendChild(document.createElement('br'))\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"765","left":"2336","inputs":{},"outputs":{}},"0.19288167008415902":{"definition":"//\n// frep slice\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep slice'\n//\n// initialization\n//\nvar init = function() {\n   mod.x0.value = ''\n   mod.x1.value = ''\n   mod.y0.value = ''\n   mod.y1.value = '0'\n   mod.z0.value = ''\n   mod.z1.value = ''\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'',\n      event:function(evt){\n         mod.shape = evt.detail\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         var limits = []\n         for (var v = 0; v < mod.shape.limits.length; ++v) {\n            limits[v] = []\n            limits[v][0] = mod.shape.limits[v][0]\n            limits[v][1] = mod.shape.limits[v][1]\n            }\n         var variables = mod.shape.variables\n         var fn = mod.shape.function\n         if (mod.x0.value != '') {\n            var x0 = parseFloat(mod.x0.value)\n            var xvar = variables[0]\n            fn = `Math.min((${xvar}-(${x0})),(${fn}))`\n            limits[0][0] = Math.max(limits[0][0],x0)\n            }\n         if (mod.x1.value != '') {\n            var x1 = parseFloat(mod.x1.value)\n            var xvar = variables[0]\n            fn = `Math.min(((${x1})-${xvar}),(${fn}))`\n            limits[0][1] = Math.min(limits[0][1],x1)\n            }\n         if (mod.y0.value != '') {\n            var y0 = parseFloat(mod.y0.value)\n            var yvar = variables[1]\n            fn = `Math.min((${yvar}-(${y0})),(${fn}))`\n            limits[1][0] = Math.max(limits[1][0],y0)\n            }\n         if (mod.y1.value != '') {\n            var y1 = parseFloat(mod.y1.value)\n            var yvar = variables[1]\n            fn = `Math.min(((${y1})-${yvar}),(${fn}))`\n            limits[1][1] = Math.min(limits[1][1],y1)\n            }\n         if (mod.z0.value != '') {\n            var z0 = parseFloat(mod.z0.value)\n            var zvar = variables[2]\n            fn = `Math.min((${zvar}-(${z0})),(${fn}))`\n            limits[2][0] = Math.max(limits[2][0],z0)\n            }\n         if (mod.z1.value != '') {\n            var z1 = parseFloat(mod.z1.value)\n            var zvar = variables[2]\n            fn = `Math.min(((${z1})-${zvar}),(${fn}))`\n            limits[2][1] = Math.min(limits[2][1],z1)\n            }\n         var shape = {function:fn,variables:mod.shape.variables,limits:limits,type:mod.shape.type}\n         mod.fn.value = fn\n         mods.output(mod,'shape',shape)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // x0\n   //\n   div.appendChild(document.createTextNode('x0: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.x0 = input\n   //\n   // x1\n   //\n   div.appendChild(document.createTextNode(' x1: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.x1 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // y0\n   //\n   div.appendChild(document.createTextNode('y0: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.y0 = input\n   //\n   // y1\n   //\n   div.appendChild(document.createTextNode(' y1: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.y1 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // z0\n   //\n   div.appendChild(document.createTextNode('z0: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.z0 = input\n   //\n   // z1\n   //\n   div.appendChild(document.createTextNode(' z1: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.z1 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // function\n   //\n   div.appendChild(document.createTextNode('function: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"426","left":"1910","inputs":{},"outputs":{}},"0.8080126368305371":{"definition":"//\n// frep taper \n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep taper'\n//\n// initialization\n//\nvar init = function() {\n   mod.variable0.value = '-1'\n   mod.variable1.value = '1'\n   mod.scale0.value = '.5'\n   mod.scale1.value = '2'\n   mod.originx.value = '0'\n   mod.originy.value = '0'\n   mod.xy.checked = true\n   mod.xz.checked = false\n   mod.yz.checked = false\n   mod.xyz.checked = false\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'',\n      event:function(evt){\n         mod.shape = evt.detail\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'',\n      event:function(){\n         var fn = mod.shape.function\n         var variables = mod.shape.variables\n         var type = mod.shape.type        \n         var var0 = parseFloat(mod.variable0.value)\n         var var1 = parseFloat(mod.variable1.value)\n         var dvar = var1-var0\n         var s0 = parseFloat(mod.scale0.value)\n         var s1 = parseFloat(mod.scale1.value)\n         var ds = s1-s0\n         var ox = parseFloat(mod.originx.value)\n         var oy = parseFloat(mod.originy.value)\n         var limits = []\n         for (var v = 0; v < mod.shape.limits.length; ++v) {\n            limits[v] = []\n            limits[v][0] = mod.shape.limits[v][0]\n            limits[v][1] = mod.shape.limits[v][1]\n            }\n         if (mod.xy.checked) {\n            var xvar = variables[0]\n            var yvar = variables[1]\n            var re = new RegExp(xvar,'g')\n            fn = fn.replace(re,`((${ox})+(${xvar}-(${ox}))/((${s0})+(${ds})*(${yvar}-(${var0}))/(${dvar})))`)\n            var xmin = limits[0][0]\n            var xmax = limits[0][1]\n            var ymin = limits[1][0]\n            var ymax = limits[1][1]\n            var x00 = ox+(xmin-ox)*(s0+ds*(ymin-var0)/dvar)\n            var x01 = ox+(xmin-ox)*(s0+ds*(ymax-var0)/dvar)\n            limits[0][0] = Math.min(x00,x01)\n            var x10 = ox+(xmax-ox)*(s0+ds*(ymin-var0)/dvar)\n            var x11 = ox+(xmax-ox)*(s0+ds*(ymax-var0)/dvar)\n            limits[0][1] = Math.max(x10,x11)\n            }\n         else if (mod.xz.checked) {\n            var xvar = variables[0]\n            var zvar = variables[2]\n            var re = new RegExp(xvar,'g')\n            fn = fn.replace(re,`((${ox})+(${xvar}-(${ox}))/((${s0})+(${ds})*(${zvar}-(${var0}))/(${dvar})))`)\n            var xmin = limits[0][0]\n            var xmax = limits[0][1]\n            var zmin = limits[2][0]\n            var zmax = limits[2][1]\n            var x00 = ox+(xmin-ox)*(s0+ds*(zmin-var0)/dvar)\n            var x01 = ox+(xmin-ox)*(s0+ds*(zmax-var0)/dvar)\n            limits[0][0] = Math.min(x00,x01)\n            var x10 = ox+(xmax-ox)*(s0+ds*(zmin-var0)/dvar)\n            var x11 = ox+(xmax-ox)*(s0+ds*(zmax-var0)/dvar)\n            limits[0][1] = Math.max(x10,x11)\n            }\n         else if (mod.yz.checked) {\n            var yvar = variables[1]\n            var zvar = variables[2]\n            var re = new RegExp(yvar,'g')\n            fn = fn.replace(re,`((${oy})+(${yvar}-(${oy}))/((${s0})+(${ds})*(${zvar}-(${var0}))/(${dvar})))`)\n            var ymin = limits[1][0]\n            var ymax = limits[1][1]\n            var zmin = limits[2][0]\n            var zmax = limits[2][1]\n            var y00 = oy+(ymin-oy)*(s0+ds*(zmin-var0)/dvar)\n            var y01 = oy+(ymin-oy)*(s0+ds*(zmax-var0)/dvar)\n            limits[1][0] = Math.min(y00,y01)\n            var y10 = oy+(ymax-oy)*(s0+ds*(zmin-var0)/dvar)\n            var y11 = oy+(ymax-oy)*(s0+ds*(zmax-var0)/dvar)\n            limits[1][1] = Math.max(y10,y11)\n            }\n         else if (mod.xyz.checked) {\n            var xvar = variables[0]\n            var yvar = variables[1]\n            var zvar = variables[2]\n            var xre = new RegExp(xvar,'g')\n            var yre = new RegExp(yvar,'g')\n            fn = fn.replace(xre,`((${ox})+(${xvar}-(${ox}))/((${s0})+(${ds})*(${zvar}-(${var0}))/(${dvar})))`)\n            fn = fn.replace(yre,`((${oy})+(${yvar}-(${oy}))/((${s0})+(${ds})*(${zvar}-(${var0}))/(${dvar})))`)\n            var xmin = limits[0][0]\n            var xmax = limits[0][1]\n            var zmin = limits[2][0]\n            var zmax = limits[2][1]\n            var x00 = ox+(xmin-ox)*(s0+ds*(zmin-var0)/dvar)\n            var x01 = ox+(xmin-ox)*(s0+ds*(zmax-var0)/dvar)\n            limits[0][0] = Math.min(x00,x01)\n            var x10 = ox+(xmax-ox)*(s0+ds*(zmin-var0)/dvar)\n            var x11 = ox+(xmax-ox)*(s0+ds*(zmax-var0)/dvar)\n            limits[0][1] = Math.max(x10,x11)\n            var ymin = limits[1][0]\n            var ymax = limits[1][1]\n            var y00 = oy+(ymin-oy)*(s0+ds*(zmin-var0)/dvar)\n            var y01 = oy+(ymin-oy)*(s0+ds*(zmax-var0)/dvar)\n            limits[1][0] = Math.min(y00,y01)\n            var y10 = oy+(ymax-oy)*(s0+ds*(zmin-var0)/dvar)\n            var y11 = oy+(ymax-oy)*(s0+ds*(zmax-var0)/dvar)\n            limits[1][1] = Math.max(y10,y11)\n            }\n         var shape = {function:fn,variables:variables,limits:limits,type:type}\n         mods.output(mod,'shape',shape)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // direction \n   //\n   div.appendChild(document.createTextNode('direction: '))\n   div.appendChild(document.createElement('br'))\n   div.appendChild(document.createTextNode('x(y)'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      div.appendChild(input)\n      mod.xy = input\n   div.appendChild(document.createTextNode(' x(z)'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      div.appendChild(input)\n      mod.xz = input\n   div.appendChild(document.createTextNode(' y(z)'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      div.appendChild(input)\n      mod.yz = input\n   div.appendChild(document.createTextNode(' xy(z)'))\n   var input = document.createElement('input')\n      input.type = 'radio'\n      input.name = mod.div.id+'axis'\n      div.appendChild(input)\n      mod.xyz = input\n   div.appendChild(document.createElement('br'))\n   //\n   // variable 0\n   //\n   div.appendChild(document.createTextNode('at: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.variable0 = input\n   //\n   // scale 0\n   //\n   div.appendChild(document.createTextNode(' scale by: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.scale0 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // variable 1\n   //\n   div.appendChild(document.createTextNode('at: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.variable1 = input\n   //\n   // scale 1\n   //\n   div.appendChild(document.createTextNode(' scale by: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.scale1 = input\n   div.appendChild(document.createElement('br'))\n   //\n   // x origin\n   //\n   div.appendChild(document.createTextNode('origin x: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.originx = input\n   //\n   // y origin\n   //\n   div.appendChild(document.createTextNode(' y: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.originy = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"306","left":"2275","inputs":{},"outputs":{}},"0.01016844222037161":{"definition":"//\n// frep inflate\n//    todo: better Z limit\n//\n// Neil Gershenfeld\n// (c) Massachusetts Institute of Technology 2018\n//\n// This work may be reproduced, modified, distributed, performed, and\n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is\n// provided as is; no warranty is provided, and users accept all\n// liability.\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'frep inflate'\n//\n// initialization\n//\nvar init = function() {\n   mod.scale.value = '1'\n   }\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'2D',\n      event:function(evt){\n         mod.shape = evt.detail\n         outputs.shape.event()\n         }}}\n//\n// outputs\n//\nvar outputs = {\n   shape:{type:'3D',\n      event:function(){\n         var variables = []\n         variables[0] = mod.shape.variables[0]\n         variables[1] = mod.shape.variables[1]\n         variables[2] = 'Z'\n         var scale = parseFloat(mod.scale.value)\n         var limits = []\n         limits[0] = [mod.shape.limits[0][0],mod.shape.limits[0][1]]\n         limits[1] = [mod.shape.limits[1][0],mod.shape.limits[1][1]]\n         limits[2] = [0,limits[0][1]-limits[0][0]]\n         fn = `((${scale})*(${mod.shape.function})-Z)`\n         fn = `Math.min(${mod.shape.function},${fn})`\n         fn = `Math.min(Z,${fn})`\n         var shape = {function:fn,variables:variables,limits:limits,type:mod.shape.type}\n         mod.fn.value = fn\n         mods.output(mod,'shape',shape)}\n         }}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // scale\n   //\n   div.appendChild(document.createTextNode('scale: '))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 3\n      div.appendChild(input)\n      mod.scale = input\n   div.appendChild(document.createElement('br'))\n   //\n   // function\n   //\n   div.appendChild(document.createTextNode('function: '))\n   div.appendChild(document.createElement('br'))\n   var input = document.createElement('input')\n      input.type = 'text'\n      input.size = 10\n      div.appendChild(input)\n      mod.fn = input\n   div.appendChild(document.createElement('br'))\n   //\n   // output button\n   //\n   var btn = document.createElement('button')\n      btn.style.padding = mods.ui.padding\n      btn.style.margin = 1\n      btn.appendChild(document.createTextNode('output'))\n      btn.addEventListener('click',function(){\n         outputs.shape.event()\n         })\n      div.appendChild(btn)\n   }\n//\n// local functions\n//\n;\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   })\n}())\n","top":"1068","left":"2361","inputs":{},"outputs":{}},"0.400055301726435":{"definition":"//\n// frep GPU volume renderer\n//\n// Neil Gershenfeld and Amira Abdel-Rahman\n// (c) Massachusetts Institute of Technology 2016\n// \n// This work may be reproduced, modified, distributed, performed, and \n// displayed for any purpose, but must acknowledge the mods\n// project. Copyright is retained and must be preserved. The work is \n// provided as is; no warranty is provided, and users accept all \n// liability.\n//\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {};\n//\n// name\n//\nvar name = 'render GPU';\n//\n// initialization\n//\nvar init = function() {\n   mod.steps.value=256.0;\n   mod.alphaCorrection=10.0;\n   mod.rendType=\"0\";\n   mod.windowOpen=false;\n   mod.xLimit1 =-1.0 ;\n   mod.xLimit2 =1.0 ; \n   mod.yLimit1 =-1.0 ; \n   mod.yLimit2 =1.0 ; \n   mod.zLimit1 =-1.0 ; \n   mod.zLimit2 =1.0 ;\n   mod.height=10.0;\n   mod.width=10.0;\n   mod.rendPerformance=0;\n   };\n//\n// inputs\n//\nvar inputs = {\n   shape:{type:'frep',\n   event:function(evt){\n\n      mod.shape=evt.detail;\n\n      // outputs.messageLog.event(mod.shape.limits);\n\n      //get largerst range and rescale other ones to adjust limit mapping\n      var tempIndex=0;\n      var tempMax=-1.0;\n\n      for(i=0;i<mod.shape.limits.length;i++)\n      {\n         if((mod.shape.limits[i][1]-mod.shape.limits[i][0]) >= tempMax )\n         {\n            tempIndex=i;\n            tempMax=mod.shape.limits[i][1]-mod.shape.limits[i][0];\n         }\n      }\n      for(i=0;i < mod.shape.limits.length;i++)\n      {\n         if(i!=tempIndex)\n         {\n            var tempDif = (mod.shape.limits[tempIndex][1]-mod.shape.limits[tempIndex][0])-(mod.shape.limits[i][1]-mod.shape.limits[i][0]);\n            mod.shape.limits[i][0]-=tempDif/2.0;\n            mod.shape.limits[i][1]+=tempDif/2.0;\n            \n         }\n      }\n\n      mod.xLimit1=mod.shape.limits[0][0] ;\n      mod.xLimit2=mod.shape.limits[0][1] ; \n      mod.yLimit1=mod.shape.limits[1][0] ; \n      mod.yLimit2=mod.shape.limits[1][1] ; \n      mod.zLimit1=mod.shape.limits[2][0] ; \n      mod.zLimit2=mod.shape.limits[2][1] ;\n      \n      //\n      //turn function string to glsl\n\t  //\n\t  \n\t  //remove all Math.\n      var str1 = mod.shape.function;\n\t  str1=str1.replace(/Math./g, '');\n\t  \n\t  //change atan2 functions to atan\n\t  str1=str1.replace(/atan2/g, \"atan\");\n         \n      //change all % to mod(,)\n      while(str1.indexOf(\"%\")>-1) //While '%' is there\n      {\n         //get location\n         var modLocation=str1.indexOf(\"%\");\n         //replace with ','\n         str1=str1.replace(/%/, \",\");\n         outputs.messageLog.event(\"1:\"+str1);\n\n         //parse before\n         var counterBefore=modLocation;\n         var count=0;\n         if(str1[--counterBefore]==')')\n         {\n            count++;\n            while(count>0)\n            {\n               counterBefore--;\n               if(str1[counterBefore]==')')\n               {\n                  count++;\n\n               }else if (str1[counterBefore]=='(')\n               {\n                  count--;\n               }\n            }\n         }else{\n            while(!isNaN(str1[counterBefore]) ||(str1[counterBefore]=='.')||(str1[counterBefore]=='X') ||(str1[counterBefore]=='Y')||(str1[counterBefore]=='Z'))\n            {\n               counterBefore--;\n            }\n\n         }\n         \n         \n         //parse after\n         var counterAfter=modLocation;\n         count=0;\n         if(str1[++counterAfter]=='(')\n         {\n            count++;\n            while(count>0)\n            {\n               counterAfter++;\n               if(str1[counterAfter]=='(')\n               {\n                  count++;\n\n               }else if (str1[counterAfter]==')')\n               {\n                  count--;\n               }\n            }\n         }else\n         {\n            while(!isNaN(str1[counterAfter]) ||(str1[counterAfter]=='.')||(str1[counterAfter]=='X') ||(str1[counterAfter]=='Y')||(str1[counterAfter]=='Z'))\n            {\n               counterAfter++;\n            }\n         }\n         \n         str1 = str1.substr(0, counterAfter) + \")\" + str1.substr(counterAfter);\n         str1 = str1.substr(0, counterBefore) + \"mod(\" + str1.substr(counterBefore);\n      }\n\n      //turn all ints to floatS\n      var str='';\n      for(var i=0;i<str1.length;i++)\n      {\n         //if number\n         if(!isNaN(str1[i]))\n         {\n            str+=str1[i];\n            //check next value\n            for(var j=i+1;j<str1.length;j++)\n            {\n            //if number add and continue\n            if(!isNaN(str1[j])) \n            {\n               str+=str1[j];\n               i=j;\n            }\n            //else if dot add and add numbers till NaN\n            else if(str1[j]=='.')\n            {\n               str+=str1[j];\n               i=j;\n               //add till not num\n               for(var k=j+1;k<str1.length;k++)\n               {\n                  if( ( !isNaN(str1[k]) )||str1[k]=='e')\n                  {\n                     //fix for scientific notation\n                     if(str1[k]=='e' && str1[k+1]=='-')\n                     {\n                        str+=str1[k];\n                        i=k;\n\n                        k++;\n\n                        str+=str1[k];\n                        i=k;\n\n                     }else\n                     {\n                        str+=str1[k];\n                        i=k;\n\n                     }\n                     \n                  }\n                  else\n                  {\n                     k=str1.length;\n                  }\n               }\n               j=str1.length;\n            }\n            //else add .0 and go to next number\n            else\n            {\n               str+='.';\n               str+='0';\n               j=str1.length;\n            }\n            }\n\n         }\n         else\n         {\n            str+=str1[i];\n         }\n      }\n      \n      mod.str=str;\n      outputs.messageLog.event(str);\n\n      //if window open update shader function\n      if(mod.windowOpen)\n      {\n         mod.updateShaderFunction();\n      }\n\n      }}};\n//\n// outputs\n//\nvar outputs = {\n    messageLog:{type:'string',\n      event:function(mess){\n      //show processed function\n        mods.output(mod,'messageLog',mess);\n      }\n    }\n}\n//\n// interface\n//\nvar interface = function(div){\n   mod.div = div\n   //\n   // on-screen drawing canvas\n   //\n   var canvas = document.createElement('canvas');\n      canvas.width = mods.ui.canvas;\n      canvas.height = mods.ui.canvas;\n      canvas.style.backgroundColor = 'rgb(0,0,0)';\n      div.appendChild(canvas);\n      mod.canvas = canvas;\n   div.appendChild(document.createElement('br'));\n   //\n   // resolution\n   //\n   div.appendChild(document.createTextNode('resolution: '));\n   var input = document.createElement('input');\n      input.type = 'text';\n      input.size = 3;\n      input.addEventListener('input',function(){\n         if(mod.windowOpen)\n         {\n            mod.redraw(true);\n         }\n         });\n      div.appendChild(input);\n      mod.steps = input;\n   div.appendChild(document.createElement('br'));\n   //\n   // adaptive rendering\n   //\n   div.appendChild(document.createTextNode('rendering performance: '))\n            var input = document.createElement('SELECT');\n            \n         input.setAttribute(\"id\", \"rend-adpselect\");\n         \n         //select menu for functions\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"0\");\n         var t = document.createTextNode('constant');\n         z.appendChild(t);\n         input.appendChild(z);\n\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"1\");\n         var t = document.createTextNode('adaptive');\n         z.appendChild(t);\n         input.appendChild(z);\n         input.addEventListener('change',function(evt){\n            var temp= document.getElementById(\"rend-adpselect\");\n            mod.rendPerformance=parseInt(temp.value);\n            mod.updateShaderFunction();\n            });\n\n         div.appendChild(input);\n  \n   div.appendChild(document.createElement('br'));\n   //\n   // rendering style\n   //\n   div.appendChild(document.createTextNode('rendering style: '))\n            var input = document.createElement('SELECT');\n            \n         input.setAttribute(\"id\", \"rend-select\");\n         \n         //select menu for functions\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"0\");\n         var t = document.createTextNode('default');\n         z.appendChild(t);\n         input.appendChild(z);\n\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"1\");\n         var t = document.createTextNode('xray');\n         z.appendChild(t);\n         input.appendChild(z);\n\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"2\");\n         var t = document.createTextNode('height map (fixed)');\n         z.appendChild(t);\n         input.appendChild(z);\n\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"3\");\n         var t = document.createTextNode('height map (variable)');\n         z.appendChild(t);\n         input.appendChild(z);\n\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"4\");\n         var t = document.createTextNode('normals');\n         z.appendChild(t);\n         input.appendChild(z);\n\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"5\");\n         var t = document.createTextNode('light');\n         z.appendChild(t);\n         input.appendChild(z);\n\n         var z = document.createElement(\"option\");\n         z.setAttribute(\"value\", \"6\");\n         var t = document.createTextNode('specular');\n         z.appendChild(t);\n         input.appendChild(z);\n       \n         input.addEventListener('change',function(evt){\n            var temp= document.getElementById(\"rend-select\");\n            mod.rendType=String(parseInt(temp.value));\n            mod.updateShaderFunction();\n            });\n\n         div.appendChild(input);\n   div.appendChild(document.createElement('br'));\n  \n   //\n   // view\n   //   \n   div.appendChild(document.createElement('br'))  ; \n   var btn = document.createElement('button');\n      btn.style.padding = mods.ui.padding;\n      btn.style.margin = 1;\n      var span = document.createElement('span');\n         var text = document.createTextNode('view');\n            span.appendChild(text);\n         btn.appendChild(span);\n      btn.addEventListener('click',function(){\n      mod.windowOpen=true; \n         open_view_window();\n         });\n      div.appendChild(btn);\n}\n\n//\n// local functions\n//\n \n//\n// open_view_window\n//\nfunction open_view_window() {\n    //\n    // globals\n    //\n    var container;\n    var camera, sceneFirstPass, sceneSecondPass, renderer;\n    var containerAxes, cameraAxes , sceneAxes, rendererAxes,axes,sphereO;\n    var rtTexture;\n    var materialSecondPass;\n    var center;\n    var meshSecondPass;\n    var boxGeometry;\n    var gridHelper;\n    var gridHelpersSize=5;\n    var clock;\n    var delta=0;\n    var interval=10;\n    var frameID;\n\n    //\n    // functions\n    //\n   \n    addShaderScripts();\n    open_window();\n   \n    //\n    // open_window\n    //\n    function open_window() \n    {\n      //\n      // open window\n      //\n      win = window.open('');\n      mod.win = win;\n\n      //\n      // load three.js\n      //\n      var script = document.createElement('script');\n      script.type = 'text/javascript';\n      script.onload = init_window;\n      script.src = 'js/three.js/three.min.js';\n      mod.div.appendChild(script);\n    }\n\n      //\n      // add shader scripts to html\n      //\n      function addShaderScripts() \n      {\n\n            /////////////////////////fragmentShaderFirstPass////////////////////////////////////\n\n            var div = document.createElement('script');\n\n            div.id = 'fragmentShaderFirstPass';\n            div.type = 'x-shader/x-fragment';\n\n            div.innerHTML =\n            `\n                  varying vec3 worldSpaceCoords;\n\n                  void main()\n                  {\n                  //The fragment's world space coordinates as fragment output.\n                  gl_FragColor = vec4( worldSpaceCoords.x , worldSpaceCoords.y, worldSpaceCoords.z, 1 );\n                  }\n                  `;\n            \n            //\n            mod.div.appendChild(div);\n            \n            /////////////////////////vertexShaderFirstPass////////////////////////////////////\n            var div = document.createElement('script');\n\n            div.id = 'vertexShaderFirstPass';\n            div.type = 'x-shader/x-vertex';\n\n            div.innerHTML =\n            `\n                  varying vec3 worldSpaceCoords;\n\n                  void main()\n                  {\n                  //Set the world space coordinates of the back faces vertices as output.\n                  worldSpaceCoords = position + vec3(0.5, 0.5, 0.5); //move it from [-0.5;0.5] to [0,1]\n                  gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n                  }\n                  `;\n            \n            //\n            mod.div.appendChild(div);\n            /////////////////////////fragmentShaderSecondPass////////////////////////////////////\n            var div = document.createElement('script');\n\n            div.id = 'fragmentShaderSecondPass';\n            div.type = 'x-shader/x-fragment';\n\n            \n            div.innerHTML=fragmentShaderSecondPass();\n            mod.div.appendChild(div);\n\n            /////////////////////vertexShaderSecondPass///////////////////\n            var div = document.createElement('script');\n\n            div.id = 'vertexShaderSecondPass';\n            div.type = 'x-shader/x-vertex';\n\n            div.innerHTML =\n            `\n                  varying vec3 worldSpaceCoords;\n                  varying vec4 projectedCoords;\n\n\n                  void main()\n                  {\n                  \n                  worldSpaceCoords = (modelMatrix * vec4(position + vec3(0.5, 0.5,0.5), 1.0 )).xyz;\n                  gl_Position = projectionMatrix *  modelViewMatrix * vec4( position, 1.0 );\n                  projectedCoords =  projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n                  }\n                  `;\n            //\n            mod.div.appendChild(div);\n      }\n   \n   //\n   // fragment shader (the one that does all the work)\n   //\n   function fragmentShaderSecondPass()\n   {\n      var txt =\n         `\n            const float PI = 3.1415926535897932384626433832795;\n            #define rendType `+mod.rendType+`\n            varying vec3 worldSpaceCoords;\n            varying vec4 projectedCoords;\n            uniform sampler2D tex;\n            uniform float steps;\n            uniform float alphaCorrection;\n            // uniform float rendType;\n            uniform vec3 cameraPos;\n            // The maximum distance through our rendering volume is sqrt(3).\n            // The maximum number of steps we take to travel a distance of 1 is 512.\n            // ceil( sqrt(3) * 512 ) = 887\n            // This prevents the back of the image from getting cut off when steps=512 & viewing diagonally.\n            const int MAX_STEPS = 887;\n            uniform float xLimit1;\n            uniform float xLimit2;\n            uniform float yLimit1;\n            uniform float yLimit2;\n            uniform float zLimit1;\n            uniform float zLimit2;\n            float orgMin=0.0;\n            float orgMax=1.0;\n            vec3 viewDirection;\n            \n\n            float map(vec3 p)\n            {\n               float X= p.x;\n               float Y= p.y;\n               float Z= p.z;\n\n               return `+mod.str+`;\n            }\n            vec3 simpleLambert (vec3 normal) {\n               vec3 lightDir = vec3(0.2,-0.6,-0.4);   // Light direction\n               vec3 lightDir1 = vec3(0.4, 0.6,-0.4);  // Light direction\n               vec3 lightCol = vec3(0.5,0.5,0.5);     // Light color\n               vec3 _Color=vec3(0.2,0.5,0.8);\n               float lightIntensity = 3.0;\n               float ambient = 0.2;\n               \n               float NdotL = max(dot(normalize(normal), normalize(lightDir)),0.0) * lightIntensity;\n               float NdotL1 = max(dot(normalize(normal), normalize(lightDir1)),0.0) *lightIntensity;\n\n               vec3 c=vec3(0.0,0.0,0.0);\n\n               c.rgb = _Color * lightCol * (NdotL + NdotL1)+ ambient ;\n\n               return c;\n            }\n            vec3 specular (vec3 normal) {\n               vec3 lightDir = vec3(0.2,-0.6,-0.4);   // Light direction\n               vec3 lightDir1 = vec3(0.4, 0.6,-0.4);  // Light direction\n               vec3 lightCol = vec3(0.5,0.5,0.5);     // Light color\n               vec3 _Color=vec3(0.2,0.5,0.8);\n               float lightIntensity=3.0;\n               float ambient = 0.2;\n\n               float _SpecularPower=0.7;\n               float _Gloss=0.7;\n               \n               float NdotL = max(dot(normalize(normal ), normalize(lightDir)),0.0)*lightIntensity;\n               float NdotL1 = max(dot(normalize(normal), normalize(lightDir1)),0.0)*lightIntensity;\n               vec3 c;\n               vec3 camera= cameraPos-0.5;\n\n               float t= dot(normalize(lightDir), normalize( -camera));\n               float tt=(dot(normalize(normal), normalize(-camera)));\n               float s= ( t*_Gloss + tt*_SpecularPower)/lightIntensity;\n\n               float t1= dot(normalize(lightDir1), normalize( -camera));\n               float tt1=(dot(normalize(normal), normalize(-camera)));\n               float s1= ( t1*_Gloss * tt1*_SpecularPower)/2.0;\n\n               // float s = pow( dot(normalize(normal),h), _SpecularPower) * _Gloss;\n               // h.x= (h.x - orgMin) * ((1.0) - (-1.0)) / (orgMax - orgMin) + (-1.0);\n               // h.y= (h.y - orgMin) * ((1.0) - (-1.0)) / (orgMax - orgMin) + (-1.0);\n               // h.z= (h.z - orgMin) * ((1.0) - (-1.0)) / (orgMax - orgMin) + (-1.0);\n               // vec3 h1 =  (lightDir1 + camera)/2.0;\n               // float s1 = pow( dot(normalize(normal)/2.0,h1), _SpecularPower) * _Gloss;\n\n               c.rgb = _Color * lightCol * (NdotL+NdotL1)+s + s1+ ambient;\n               return c;\n            }\n            vec3 frontLight (vec3 normal) {\n               \n                  vec3 camera= cameraPos-0.5;\n                  float t=dot(normalize(normal), normalize(-camera));\n                  vec3 c;\n                  c = vec3(t,t,t);\n                  return c;\n            }\n\n            vec3 ClosestPointOnLine(vec3 start ,vec3 direction ,vec3 vPoint )\n            {\n               vec3 vVector1 = vPoint - start;\n               vec3 vVector2 = normalize(direction);\n            \n               float t = dot(vVector2, vVector1);\n               if (t <= 0.0)\n               {\n                  return start;\n               }\n                  \n               vec3 vVector3 = vVector2 * t;\n            \n               vec3 vClosestPoint = start + vVector3;\n               return vClosestPoint;\n            }\n            vec3 GetClosetPoint( vec3 A, vec3 B, vec3 P, bool segmentClamp)\n            {\n               vec3 AP = P - A;\n               vec3 AB = B - A; \n               float ab2 = AB.x*AB.x + AB.y*AB.y;\n               float apab = AP.x*AB.x + AP.y*AB.y;\n               float t = apab / ab2;\n               if (segmentClamp)\n               {\n                  if (t < 0.0) t = 0.0;\n                  else if (t > 1.0) t = 1.0;\n               }\n               vec3 Closest = A + AB * t;\n               return Closest;\n            }\n            vec3 calcNormal( in vec3 pos )\n            {\n                  // vec2 e = vec2(1.0,-1.0)*0.5773*0.0005;\n                  // return normalize( e.xyy*map( pos + e.xyy ) + \n                  //                         e.yyx*map( pos + e.yyx ) + \n                  //                         e.yxy*map( pos + e.yxy ) + \n                  //                         e.xxx*map( pos + e.xxx ) );\n                  \n                  // vec3 eps = vec3( 0.0005, 0.0, 0.0 );\n                  // vec3 nor = vec3(\n                  //       map(pos+eps.xyy) - map(pos-eps.xyy),\n                  //       map(pos+eps.yxy) - map(pos-eps.yxy),\n                  //       map(pos+eps.yyx) - map(pos-eps.yyx) );\n                  // return normalize(nor);\n\n                  const float eps = 0.01;\n                  vec3 n;\n                  n.x=map(pos + vec3(eps, 0, 0)   ) - map(pos - vec3(eps, 0, 0));\n                  n.y=map(pos + vec3(0, eps, 0)   ) - map(pos - vec3(0, eps, 0));\n                  n.z=map(pos + vec3(0, 0, eps)   ) - map(pos - vec3(0, 0, eps));\n                  //problem with \n                  // n.x=result - map(pos - vec3(eps, 0, 0));\n                  // n.y=result - map(pos - vec3(0, eps, 0));\n                  // n.z=result - map(pos - vec3(0, 0, eps));\n                  return normalize(n);\n                  \n            }\n\n            //Acts like a texture3D using Z slices and trilinear filtering.\n            vec4 sampleAs3DTextureCustom( vec3 texCoord )\n            { \n               float X= (texCoord.x - orgMin) * (xLimit2 - xLimit1) / (orgMax - orgMin) + xLimit1;\n               float Y= (texCoord.y - orgMin) * (yLimit2 - yLimit1) / (orgMax - orgMin) + yLimit1;\n               float Z= (texCoord.z - orgMin) * (zLimit2 - zLimit1) / (orgMax - orgMin) + zLimit1;\n\n               //slice color red\n               vec4 m;\n               m=vec4(0.0,0.0,0.0,0.0);\n\n               float result=`+mod.str+`;\n               if(result>0.0)\n               {\n                  m.a=1.0;\n                  vec3 p=vec3(X,Y,Z);\n                  vec3 n=calcNormal( p );\n\n                  #if rendType==0\n                  //default\n                     {\n                        float tempConst=0.001;\n                        m.rgb=frontLight(n)+tempConst;\n                     }\n                  #elif rendType==1\n                  //xray\n                     {\n                        m=vec4(1.0,1.0,1.0,0.01);\n                     }\n                  #elif rendType==2\n                  //height map\n                     {\n                        m.r=texCoord.z;\n                        m.g=texCoord.z;\n                        m.b=texCoord.z;\n                     }\n                  #elif rendType==3\n                  //depth/height map variable\n                     {\n                        vec3 cp=ClosestPointOnLine(-cameraPos,cameraPos,texCoord);\n                        float d= (distance(cp, normalize(cameraPos)*2.0));\n                        m.r=d;\n                        m.g=d;\n                        m.b=d;\n                     }\n                  #elif rendType==4\n                  //normals\n                     {\n                        m.r= (n.r - (-1.0)) * (1.0 - 0.0) / (1.0 - (-1.0)) + 0.0;\n                        m.g= (n.g - (-1.0)) * (1.0 - 0.0) / (1.0 - (-1.0)) + 0.0;\n                        m.b= (n.b - (-1.0)) * (1.0 - 0.0) / (1.0 - (-1.0)) + 0.0;\n                     }\n                  #elif rendType==5\n                  //fixed lights\n                     {\n                        float tempConst=0.05;\n                        m.rgb=simpleLambert (n)+tempConst;\n                     }\n                  #elif rendType==6\n                  //fixed lights specular\n                     {\n                        float tempConst=0.00;\n                        m.rgb=specular (n)+tempConst;\n                     }\n                  #endif\n                  \n               }\n               return m ;\n            }\n            \n            void main( void ) {\n\n               //Transform the coordinates it from [-1;1] to [0;1]\n               vec2 texc = vec2(((projectedCoords.x / projectedCoords.w) + 1.0 ) / 2.0,\n                           ((projectedCoords.y / projectedCoords.w) + 1.0 ) / 2.0 );\n\n               //The back position is the world space position stored in the texture.\n               vec3 backPos = texture2D(tex, texc).xyz;\n\n               //The front position is the world space position of the second render pass.\n               vec3 frontPos = worldSpaceCoords;\n\n               //The direction from the front position to back position.\n               vec3 dir = backPos - frontPos;\n               \n               float rayLength = length(dir);\n\n               //Calculate how long to increment in each step.\n               float delta = 1.0 / steps;\n\n               //The increment in each direction for each step.\n               vec3 deltaDirection = normalize(dir) * delta;\n\n               viewDirection=normalize(dir);//amira added\n\n               float deltaDirectionLength = length(deltaDirection);\n\n               //Start the ray casting from the front position.\n               vec3 currentPosition = frontPos;\n\n               //The color accumulator.\n               vec4 accumulatedColor = vec4(0.0);\n\n               //The alpha value accumulated so far.\n               float accumulatedAlpha = 0.0;\n\n               //How long has the ray travelled so far.\n               float accumulatedLength = 0.0;\n\n               //If we have twice as many samples, we only need ~1/2 the alpha per sample.\n               //Scaling by 256/10 just happens to give a good value for the alphaCorrection slider.\n               float alphaScaleFactor = 25.6 * delta;\n\n               vec4 colorSample;\n               float alphaSample;\n\n               //Perform the ray marching iterations\n               for(int i = 0; i < MAX_STEPS; i++)\n               {\n                  //Get the voxel intensity value from the 3D texture.\n                  colorSample = sampleAs3DTextureCustom( currentPosition );\n\n                  //Allow the alpha correction customization.\n                  alphaSample = colorSample.a * alphaCorrection;\n\n                  //Applying this effect to both the color and alpha accumulation results in more realistic transparency.\n                  alphaSample *= (1.0 - accumulatedAlpha);\n\n                  //Scaling alpha by the number of steps makes the final color invariant to the step size.\n                  alphaSample *= alphaScaleFactor;\n\n                  //Perform the composition.\n                  accumulatedColor += colorSample * alphaSample;\n\n                  //Store the alpha accumulated so far.\n                  accumulatedAlpha += alphaSample;\n\n                  //Advance the ray.\n                  currentPosition += deltaDirection;\n                  accumulatedLength += deltaDirectionLength;\n\n                  //If the length traversed is more than the ray length, or if the alpha accumulated reaches 1.0 then exit.\n                  if(accumulatedLength >= rayLength || accumulatedAlpha >= 1.0 )\n                     break;\n               }\n\n               gl_FragColor  = accumulatedColor;\n\n            }\n            `;\n      return txt;\n   }\n\n    //\n    // init_window\n    //\n   function init_window() {\n      //\n      // close button\n      //\n      var btn = document.createElement('button');\n         btn.appendChild(document.createTextNode('close'));\n         btn.style.padding = mods.ui.padding;\n         btn.style.margin = 1;\n         btn.addEventListener('click',function(){\n            win.close();\n            mod.win = undefined;\n         });\n         win.document.body.appendChild(btn);\n      //\n      // label text\n      //\n      var text = win.document.createTextNode(' left: pan, right: rotate, scroll: zoom');\n         win.document.body.appendChild(text);\n      //\n      // GL container\n      //\n      win.document.body.appendChild(document.createElement('br')) ;  \n      container = win.document.createElement('div');\n      container.style.overflow = 'hidden';\n      win.document.body.appendChild(container);\n\n      ///////////////////////////////////////////axes////////////////////////////\n      //GL Axes Container\n      // win.document.body.appendChild(document.createElement('br')) ;  \n      containerAxes = win.document.createElement('div');\n      containerAxes.style.overflow = 'hidden';\n      containerAxes.style.position = 'absolute';\n      containerAxes.style.zIndex = 100;\n      containerAxes.style.left = 0;\n      containerAxes.style.bottom = 0;\n      containerAxes.style.margin = 20;\n      win.document.body.appendChild(containerAxes);\n      //\n      //cameraAxes\n      //\n      cameraAxes = new THREE.PerspectiveCamera( 50, 100 / 100, 1, 1000 );\n      cameraAxes.up = new THREE.Vector3(0, 0, 1);\n      //\n      //rendererAxes\n      //\n      rendererAxes = new THREE.WebGLRenderer({ alpha: true } );\n      rendererAxes.setClearColor( 0x000000, 0 );\n      rendererAxes.setSize( 100, 100 );\n      containerAxes.appendChild( rendererAxes.domElement );\n      //\n      //sceneAxes\n      //\n      sceneAxes=new THREE.Scene();\n      axes = new THREE.AxesHelper( 100 );\n      sceneAxes.add( axes );   \n\n      ///////////////////////////////////////////////////////////////////////////////////\n      \n      //\n      //camera\n      //\n      camera = new THREE.PerspectiveCamera( 40, win.innerWidth / win.innerHeight, 0.01, 3000.0 );\n      camera.position.z = 2.0;\n      camera.aspect = win.innerWidth / win.innerHeight;\n      camera.up = new THREE.Vector3(0, 0, 1);\n      camera.position.x = 5;\n      camera.lookAt(new THREE.Vector3(0,0,0));\n      camera.updateProjectionMatrix();\n      center= new THREE.Vector3(0,0,0);\n\n      \n      \n      //\n      //setup textures and scenes\n      //\n      var screenSize = new THREE.Vector2( win.innerWidth, win.innerHeight );\n      rtTexture = new THREE.WebGLRenderTarget( screenSize.x, screenSize.y,\n                                    {  minFilter: THREE.LinearFilter,\n                                       magFilter: THREE.LinearFilter,\n                                       wrapS:  THREE.ClampToEdgeWrapping,\n                                       wrapT:  THREE.ClampToEdgeWrapping,\n                                       format: THREE.RGBAFormat,\n                                       type: THREE.FloatType,\n                                       generateMipmaps: false} );\n\n\n      var materialFirstPass = new THREE.ShaderMaterial( {\n         vertexShader: document.getElementById( 'vertexShaderFirstPass' ).textContent,\n         fragmentShader: document.getElementById( 'fragmentShaderFirstPass' ).textContent,\n         side: THREE.BackSide\n      } );\n\n      var lookAtVector = new THREE.Vector3(0,0, -1);\n      lookAtVector.applyQuaternion(camera.quaternion);\n\n      sceneFirstPass = new THREE.Scene();\n      sceneSecondPass = new THREE.Scene();\n\n      var tempCam=new THREE.Vector3(camera.position.x,camera.position.y,camera.position.z);\n      materialSecondPass = new THREE.ShaderMaterial( {\n         vertexShader: document.getElementById( 'vertexShaderSecondPass' ).textContent,\n         fragmentShader: document.getElementById( 'fragmentShaderSecondPass' ).textContent,\n         side: THREE.FrontSide,\n         uniforms: { tex:  { type: \"t\", value: rtTexture },\n                  steps : {type: \"1f\" , value: mod.steps.value }, \n                  xLimit1 : {type: \"1f\" , value: mod.xLimit1 }, \n                  xLimit2 : {type: \"1f\" , value: mod.xLimit2 }, \n                  yLimit1 : {type: \"1f\" , value: mod.yLimit1 }, \n                  yLimit2 : {type: \"1f\" , value: mod.yLimit2 }, \n                  zLimit1 : {type: \"1f\" , value: mod.zLimit1 }, \n                  zLimit2 : {type: \"1f\" , value: mod.zLimit2 }, \n                  alphaCorrection : {type: \"1f\" , value: mod.alphaCorrection},\n                  cameraPos :{value:  tempCam.normalize()} \n               }\n      });\n\n      //HELPER GRID\n      gridHelper = new THREE.GridHelper( gridHelpersSize, 20 );//SIZE DIVISION\n      var geometry = new THREE.SphereGeometry( 0.1,32,32);\n      var material = new THREE.MeshNormalMaterial();\n      sphereO = new THREE.Mesh( geometry, material );\n\n      var materialX = new THREE.LineBasicMaterial({\n            color: 0xFF0000\n      });\n      var materialY = new THREE.LineBasicMaterial({\n            color: 0x00FF00\n      });\n      \n      var geometryX = new THREE.Geometry();\n      geometryX.vertices.push(\n            new THREE.Vector3( -5, 0, 0 ),\n            new THREE.Vector3(  5, 0, 0 )\n      );\n      var geometryY = new THREE.Geometry();\n      geometryY.vertices.push(\n            new THREE.Vector3( 0, -5, 0 ),\n            new THREE.Vector3( 0,  5, 0 )\n      );\n      \n      var lineX = new THREE.Line( geometryX, materialX );\n      var lineY = new THREE.Line( geometryY, materialY );\n\n      gridHelper.add(lineX);\n      gridHelper.add(lineY);\n      sceneSecondPass.add( gridHelper );\n      // sceneSecondPass.add( sphereO );\n      gridHelper.geometry.rotateX( Math.PI / 2 );\n      \n      updateGridHelper();\n      \n      \n      //\n      //cube renderer\n      //\n      boxGeometry = new THREE.BoxGeometry(1.0, 1.0, 1.0);\n      boxGeometry.doubleSided = true;\n\n      materialSecondPass.transparent =true;\n      var meshFirstPass = new THREE.Mesh( boxGeometry, materialFirstPass );\n      meshSecondPass = new THREE.Mesh( boxGeometry, materialSecondPass );\n\n      sceneFirstPass.add( meshFirstPass );\n      sceneSecondPass.add( meshSecondPass );\n\n      renderer = new THREE.WebGLRenderer();\n      container.appendChild( renderer.domElement );\n      renderer.setSize( win.innerWidth, win.innerHeight );\n\n\n      //\n      // mod viewer\n      //\n\n      //grab the context from your destination canvas\n      var destCtx = mod.canvas.getContext('2d');\n      destCtx.clearRect(0,0,mod.canvas.width,mod.canvas.height);\n      //call its drawImage() function passing it the source canvas directly\n      destCtx.drawImage(container.childNodes[0], 0, 0);\n\n\n      clock=new THREE.Clock();\n      //\n      //controls\n      //\n      var Controls = (function(Controls) {\n         // \"use strict\";\n      \n         // Check for double inclusion\n         if (Controls.addMouseHandler)\n            return Controls;\n      \n         Controls.addMouseHandler = function (domObject, drag, zoomIn, zoomOut) {\n            var startDragX = null,\n               startDragY = null;\n      \n            function mouseWheelHandler(e) {\n               e = window.event || e;\n               var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));\n      \n               if (delta < 0 && zoomOut) {\n                  zoomOut(delta);\n               } else if (zoomIn) {\n                  zoomIn(delta);\n               }\n      \n               e.preventDefault();\n            }\n      \n            function mouseDownHandler(e) {\n               startDragX = e.clientX;\n               startDragY = e.clientY;\n      \n               e.preventDefault();\n            }\n      \n            function mouseMoveHandler(e) {\n               if (startDragX === null || startDragY === null)\n                  return;\n      \n               if (drag)\n                  drag(e.clientX - startDragX, e.clientY - startDragY);\n      \n               startDragX = e.clientX;\n               startDragY = e.clientY;\n      \n               e.preventDefault();\n            }\n      \n            function mouseUpHandler(e) {\n               mouseMoveHandler.call(this, e);\n               startDragX = null;\n               startDragY = null;\n      \n               e.preventDefault();\n            }\n      \n            domObject.addEventListener(\"mousewheel\", mouseWheelHandler);\n            domObject.addEventListener(\"DOMMouseScroll\", mouseWheelHandler);\n            domObject.addEventListener(\"mousedown\", mouseDownHandler);\n            domObject.addEventListener(\"mousemove\", mouseMoveHandler);\n            domObject.addEventListener(\"mouseup\", mouseUpHandler);\n         };\n         return Controls;\n      }(Controls || {}));\n      Controls.addMouseHandler(renderer.domElement, drag, zoomIn, zoomOut);\n      \n\n      //\n      // event handlers\n      //\n      win.addEventListener( 'resize', onWindowResize, false );\n      win.addEventListener('contextmenu',context_menu);\n      \n      render();\n   }\n  \n   //\n   //window resize\n   //\n   function onWindowResize( event ) {\n\n      //TODO: Fix box white edge when window resize\n      renderer.setSize( win.innerWidth, win.innerHeight );\n\n      camera.aspect = win.innerWidth / win.innerHeight;\n      camera.updateProjectionMatrix();\n\n      redraw(false);\n   }\n\n   //\n   //context menu\n   //\n   function context_menu(evt) \n   {\n      evt.preventDefault();\n      evt.stopPropagation();\n      return (false);\n   }\n\n   //\n   // mouse_down\n   //\n   function mouse_down(evt) \n   { \n      evt.preventDefault();\n      evt.stopPropagation();\n      mod.button = evt.button;\n      mod.x = evt.clientX;\n      mod.y = evt.clientY;\n   }\n\n   //\n   // mouse_up\n   //\n   function mouse_up(evt) {\n      mod.button = undefined;\n      mod.x = evt.clientX;\n      mod.y = evt.clientY;\n   }\n\n   //\n   // mouse_move\n   //\n   function mouse_move(evt) \n   {\n      evt.preventDefault();\n      evt.stopPropagation();\n      var dx = evt.clientX-mod.x;\n      var dy = evt.clientY-mod.y;\n      mod.x = evt.clientX;\n      mod.y = evt.clientY;\n      if (mod.button == 0) {\n         mod.x0 += \n            Math.sin(mod.thetaz)*mod.height*dy/win.innerHeight\n            -Math.cos(mod.thetaz)*mod.width*dx/win.innerWidth;\n         mod.y0 += \n            Math.cos(mod.thetaz)*mod.height*dy/win.innerHeight\n            +Math.sin(mod.thetaz)*mod.width*dx/win.innerWidth;\n         camera.position.x = mod.x0+Math.sin(mod.thetaz)*mod.r*Math.sin(mod.thetaxy);\n         camera.position.y = mod.y0+Math.cos(mod.thetaz)*mod.r*Math.sin(mod.thetaxy);\n         camera.position.z = mod.r*Math.cos(mod.thetaxy);\n         camera.position.z = mod.r*Math.cos(mod.thetaxy);\n            camera.up = new THREE.Vector3(Math.sin(mod.thetaz),Math.cos(mod.thetaz),0);\n            camera.lookAt(new THREE.Vector3(mod.x0,mod.y0,0));\n         camera.updateProjectionMatrix();\n         redraw(false);\n      }\n      else if (mod.button == 2) {\n         mod.thetaxy += dy/win.innerHeight;\n         mod.thetaz += dx/win.innerWidth;\n         camera.position.x = mod.x0+Math.sin(mod.thetaz)*mod.r*Math.sin(mod.thetaxy);\n         camera.position.y = mod.y0+Math.cos(mod.thetaz)*mod.r*Math.sin(mod.thetaxy);\n         camera.position.z = mod.r*Math.cos(mod.thetaxy);\n            camera.up = new THREE.Vector3(Math.sin(mod.thetaz),Math.cos(mod.thetaz),0);\n            camera.lookAt(new THREE.Vector3(mod.x0,mod.y0,0));\n         camera.updateProjectionMatrix();\n            renderer.render(scene,camera);\n      }\n   }\n\n   //\n   // mouse_wheel\n   //\n   function mouse_wheel(evt) \n   {\n      evt.preventDefault();\n      evt.stopPropagation();\n      var dy = evt.deltaY/win.innerHeight;\n      mod.r += mod.height*dy;\n      camera.position.x = mod.x0+Math.sin(mod.thetaz)*mod.r*Math.sin(mod.thetaxy);\n      camera.position.y = mod.y0+Math.cos(mod.thetaz)*mod.r*Math.sin(mod.thetaxy);\n      camera.position.z = mod.r*Math.cos(mod.thetaxy);\n      camera.lookAt(new THREE.Vector3(mod.x0,mod.y0,0));\n      camera.updateProjectionMatrix();\n      redraw(false);\n   }\n\n   //\n   //redraw\n   //\n   \n\n   function frame() \n   {\n      if (delta == 5) {\n            delta=0;\n            clearInterval(frameID);\n      } else {\n            delta++; \n            render(true,mod.steps.value*delta/5);\n      }\n   }  \n\n   function redraw(updateUniforms)\n   {\n      if(mod.rendPerformance==1)\n      {\n            if(frameID!=null)\n            {\n                  clearInterval(frameID);\n            }\n            frameID=setInterval(frame, interval);   \n      }else\n      {\n            if(frameID!=null)\n            {\n                  clearInterval(frameID);\n            }\n            render(updateUniforms,mod.steps.value);\n      }\n   }\n   mod.redraw=redraw;\n\n   function updateGridHelper()\n   {\n      //TODO: later move/rotate camera based on changes\n      //update grid helper based on limits\n      gridHelper.geometry.rotateX( - Math.PI / 2 );\n      gridHelper.scale.x=gridHelpersSize/(Math.abs(mod.xLimit2  - mod.xLimit1)*gridHelpersSize/2.0);\n      gridHelper.scale.y=gridHelpersSize/(Math.abs(mod.yLimit2  - mod.yLimit1)*gridHelpersSize/2.0);\n      gridHelper.position.x=( (0.0 - (mod.xLimit1)) * (0.5  - (-0.5)) / (mod.xLimit2 - (mod.xLimit1)) + (-0.5));\n      gridHelper.position.y=( (0.0 - (mod.yLimit1)) * (0.5  - (-0.5)) / (mod.yLimit2 - (mod.yLimit1)) + (-0.5));\n      gridHelper.position.z=( (0.0 - (mod.zLimit1)) * (0.5  - (-0.5)) / (mod.zLimit2 - (mod.zLimit1)) + (-0.5));\n      gridHelper.geometry.rotateX( Math.PI / 2 );\n      \n      sphereO.scale.x=gridHelpersSize/(Math.abs(mod.xLimit2  - mod.xLimit1)*gridHelpersSize/0.5);\n      sphereO.scale.y=gridHelpersSize/(Math.abs(mod.yLimit2  - mod.yLimit1)*gridHelpersSize/0.5);\n      sphereO.scale.z=gridHelpersSize/(Math.abs(mod.zLimit2  - mod.zLimit1)*gridHelpersSize/0.5);\n     \n      sphereO.position.x=( (0.0 - (mod.xLimit1)) * (0.5  - (-0.5)) / (mod.xLimit2 - (mod.xLimit1)) + (-0.5));\n      sphereO.position.y=( (0.0 - (mod.yLimit1)) * (0.5  - (-0.5)) / (mod.yLimit2 - (mod.yLimit1)) + (-0.5));\n      sphereO.position.z=( (0.0 - (mod.zLimit1)) * (0.5  - (-0.5)) / (mod.zLimit2 - (mod.zLimit1)) + (-0.5));\n   }\n\n   //\n   //render\n   //\n   function render(updateUniforms ,resolutionStep) {\n      if(updateUniforms)\n      {\n            \n            materialSecondPass.uniforms.steps.value = resolutionStep;\n            materialSecondPass.uniforms.alphaCorrection.value = mod.alphaCorrection;\n            materialSecondPass.uniforms.xLimit1.value =mod.xLimit1 ;\n            materialSecondPass.uniforms.xLimit2.value =mod.xLimit2 ; \n            materialSecondPass.uniforms.yLimit1.value =mod.yLimit1 ; \n            materialSecondPass.uniforms.yLimit2.value =mod.yLimit2 ; \n            materialSecondPass.uniforms.zLimit1.value =mod.zLimit1 ; \n            materialSecondPass.uniforms.zLimit2.value =mod.zLimit2 ;\n\n\n            //TODO: Find the error with xray and fix it\n            if(mod.rendType=='1')//xray\n            {\n                  materialSecondPass.transparent =false;\n            }else\n            {\n                  materialSecondPass.transparent =true;\n            }\n\n            updateGridHelper();\n      }\n\n      var tempCam=new THREE.Vector3(camera.position.x,camera.position.y,camera.position.z);\n\n      materialSecondPass.uniforms.cameraPos.value=tempCam.normalize();\n      tempCam.normalize();\n      tempCam.addScalar(0.5);\n\n      //Render first pass and store the world space coords of the back face fragments into the texture.\n      //renderer.render( sceneFirstPass, camera, rtTexture, true );\n\n      //Render the second pass and perform the volume rendering.\n      //renderer.render( sceneSecondPass, camera );\n\n      var previousRenderTarget = renderer.getRenderTarget();\n\t  renderer.setRenderTarget(rtTexture);\n\t  renderer.render( sceneFirstPass, camera );\n\t  renderer.setRenderTarget( previousRenderTarget );\n\t  renderer.render( sceneSecondPass, camera );\n\n      //render axes camera\n      cameraAxes.position.x=camera.position.x;\n      cameraAxes.position.y=camera.position.y;\n      cameraAxes.position.z=camera.position.z;\n\tcameraAxes.position.sub( center ); \n\tcameraAxes.position.setLength( 300 );\n      cameraAxes.lookAt( sceneAxes.position.clone() );  \n\n      rendererAxes.render( sceneAxes, cameraAxes );\n\n      updateModViewer();\n      \n   }\n\n   //\n   //render to small mod viewer\n   //\n   function updateModViewer()\n   {\n      var w=win.innerWidth;\n      var h=win.innerHeight;\n      if (w > h) {\n         var x0 = 0;\n         var y0 = mod.canvas.height*.5*(1-h/w);\n         var wd = mod.canvas.width;\n         var hd = mod.canvas.width*h/w;\n         }\n       else {\n         var x0 = mod.canvas.width*.5*(1-w/h);\n         var y0 = 0;\n         var wd = mod.canvas.height*w/h;\n         var hd = mod.canvas.height;\n         }\n      var destCtx = mod.canvas.getContext('2d');\n      destCtx.drawImage(container.childNodes[0],x0,y0,wd,hd);\n\n   }\n\n   //\n   //when fuction changes\n   //\n   function updateShaderFunction()\n   {\n      // outputs.messageLog.event('update shader');\n      \n      // outputs.messageLog.event(mod.xLimit1);\n\n      var div = document.getElementById('fragmentShaderSecondPass');\n\n      div.innerHTML=\"\";\n      div.innerHTML =fragmentShaderSecondPass();\n      \n      var tempCam=new THREE.Vector3(camera.position.x,camera.position.y,camera.position.z);\n      // outputs.messageLog.event('update shader1');\n      materialSecondPass = new THREE.ShaderMaterial( {\n         vertexShader: document.getElementById( 'vertexShaderSecondPass' ).textContent,\n         fragmentShader: document.getElementById( 'fragmentShaderSecondPass' ).textContent,\n         side: THREE.FrontSide,\n         uniforms: { tex:  { type: \"t\", value: rtTexture },\n                  steps : {type: \"1f\" , value: mod.steps.value }, \n                  xLimit1 : {type: \"1f\" , value: mod.xLimit1 }, \n                  xLimit2 : {type: \"1f\" , value: mod.xLimit2 }, \n                  yLimit1 : {type: \"1f\" , value: mod.yLimit1 }, \n                  yLimit2 : {type: \"1f\" , value: mod.yLimit2 }, \n                  zLimit1 : {type: \"1f\" , value: mod.zLimit1 }, \n                  zLimit2 : {type: \"1f\" , value: mod.zLimit2 }, \n                  alphaCorrection : {type: \"1f\" , value: mod.alphaCorrection},\n                  cameraPos :{value: tempCam.normalize()}\n               }\n         });\n\n      //new THREE.Vector3(20.0,-60.0,-40.0)\n      meshSecondPass.material=materialSecondPass;\n      meshSecondPass.material.needsUpdate = true;\n      meshSecondPass.material.transparent =true;\n\n      redraw(true);\n\n      //test performance\n      // mod.tend = Date.now();\n      // var dt = mod.tend-mod.tstart;\n      // outputs.messageLog.event(dt/1000);\n\n   }\n   mod.updateShaderFunction=updateShaderFunction;\n      \n      //\n      //controls\n      //\n      function drag(deltaX, deltaY) \n      {\n            var radPerPixel = (Math.PI / 450),\n            deltaPhi = radPerPixel * deltaX,\n            deltaTheta = radPerPixel * deltaY,\n            pos = camera.position.sub(center),\n            radius = pos.length(),\n            theta = Math.acos(pos.z / radius),\n            phi = Math.atan2(pos.y, pos.x);\n\n            // Subtract deltaTheta and deltaPhi\n            theta = Math.min(Math.max(theta - deltaTheta, 0), Math.PI);\n            phi -= deltaPhi;\n\n            // Turn back into Cartesian coordinates\n            pos.x = radius * Math.sin(theta) * Math.cos(phi);\n            pos.y = radius * Math.sin(theta) * Math.sin(phi);\n            pos.z = radius * Math.cos(theta);\n\n            camera.position.add(center);\n            camera.lookAt(center);\n            redraw(false);\n      }\n\n      ///\n      function zoomIn() \n      {\n            camera.position.sub(center).multiplyScalar(0.9).add(center);\n            redraw(false);\n      }\n\n      ///\n      function zoomOut() \n      {\n            camera.position.sub(center).multiplyScalar(1.1).add(center);\n            redraw(false);\n      }\n}\n\n//\n// return values\n//\nreturn ({\n   mod:mod,\n   name:name,\n   init:init,\n   inputs:inputs,\n   outputs:outputs,\n   interface:interface\n   });\n}());\n\n\n","top":"1023.4653952925182","left":"2843.396641500616","inputs":{},"outputs":{}}},"links":["{\"source\":\"{\\\"id\\\":\\\"0.3625970106871924\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.9645985086194264\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape0\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.3625970106871924\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"variables\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.04772797317232935\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"in0\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.04772797317232935\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"out0\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.7152788275346978\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"variables\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.7152788275346978\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.9645985086194264\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape1\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.9645985086194264\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.9645985086194264\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"clear\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.7152788275346978\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.9458395548196141\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.9645985086194264\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.04930175848785401\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape0\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.9458395548196141\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.04930175848785401\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape1\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.3625970106871924\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.5608762029437723\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.04930175848785401\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.40238136387777756\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape0\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.5608762029437723\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.5939459494005885\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.5608762029437723\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.690161531242695\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape0\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.5939459494005885\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.690161531242695\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape1\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.690161531242695\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.690161531242695\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"clear\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.690161531242695\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.19288167008415902\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.19288167008415902\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.40238136387777756\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape1\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.40238136387777756\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.8080126368305371\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.8080126368305371\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.8373334092218472\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.8080126368305371\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.01016844222037161\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.01016844222037161\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"shape\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.400055301726435\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"shape\\\"}\"}"]}
\ No newline at end of file