diff --git a/files.html b/files.html
index 9090c07918155e70a53cb323de17c8f4bdd6970d..4804b18c817bf995894321244df1d6888eedaea6 100644
--- a/files.html
+++ b/files.html
@@ -19,6 +19,7 @@
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./js/files.js'>files.js</a><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./js/mods.js'>mods.js</a><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./js/modules.js'>modules.js</a><br>
+<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node_modules</i><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./js/printserver.js'>printserver.js</a><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./js/programs.js'>programs.js</a><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./js/serialserver.js'>serialserver.js</a><br>
@@ -193,6 +194,7 @@
 <i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frep</i><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./programs/frep/gears'>gears</a><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./programs/frep/lattice%20torus'>lattice torus</a><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./programs/frep/smiley'>smiley</a><br>
 <i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image</i><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./programs/image/function'>function</a><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./programs/image/motion%20detect'>motion detect</a><br>
diff --git a/modules/frep/shapes/2D/involute gear b/modules/frep/shapes/2D/involute gear
index a2ba7275fb3cc335844a3f0374ed4fbcbaee0072..3ee05470a0008ab9017df994214c9a9fc2b912f2 100755
--- a/modules/frep/shapes/2D/involute gear	
+++ b/modules/frep/shapes/2D/involute gear	
@@ -111,9 +111,17 @@ var outputs = {
    variables:{type:'',
       event:function(){
          var module = parseFloat(mod.module.value)
-         var angle = parseFloat(mod.angle.value)
+         var angle = Math.PI*parseFloat(mod.angle.value)/180
          var teeth = parseFloat(mod.teeth.value)
-         var vars = {module:module,angle:angle,teeth:teeth}
+         var addendum = parseFloat(mod.addendum.value)
+         var dedendum = parseFloat(mod.dedendum.value)
+         var rp = module*teeth/2 
+         var rb = rp*Math.cos(angle)
+         var ha = addendum*module
+         var hd = dedendum*module
+         var ai = Math.tan(angle)-angle 
+         var ap = 2*Math.PI/teeth
+         var vars = {module:module,angle:angle,teeth:teeth,rp:rp,rb:rb,ha:ha,hd:hd,ai:ai,ap:ap}
          mods.output(mod,'variables',vars)}
          }}
 //
diff --git a/modules/frep/shapes/2D/involute rack b/modules/frep/shapes/2D/involute rack
index f73ef40ba2cfe346126a3a366f1aa2a98c9ff561..3cada6ecc2aad583480b8dea06e98b6eec50313a 100644
--- a/modules/frep/shapes/2D/involute rack	
+++ b/modules/frep/shapes/2D/involute rack	
@@ -122,9 +122,18 @@ var outputs = {
    variables:{type:'',
       event:function(){
          var module = parseFloat(mod.module.value)
-         var angle = parseFloat(mod.angle.value)
+         var angle = Math.PI*parseFloat(mod.angle.value)/180
          var teeth = parseFloat(mod.teeth.value)
-         var vars = {module:module,angle:angle,teeth:teeth}
+         var addendum = parseFloat(mod.addendum.value)
+         var dedendum = parseFloat(mod.dedendum.value)
+         var p = Math.PI*module
+         var l = p*teeth
+         var ha = addendum*module
+         var hd = dedendum*module
+         var bt = (ha+hd)*Math.tan(angle)
+         var bp = ha*Math.tan(angle)
+         var s = 1/Math.tan(angle)
+         var vars = {module:module,angle:angle,teeth:teeth,p:p,l:l,ha:ha,hd:hd,bt:bt,bp:bp,s:s}
          mods.output(mod,'variables',vars)}
          }}
 //
diff --git a/programs/frep/smiley b/programs/frep/smiley
new file mode 100644
index 0000000000000000000000000000000000000000..1788720798771c594530b6908046b5437f5a7ab8
--- /dev/null
+++ b/programs/frep/smiley
@@ -0,0 +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":{}}},"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\\\"}\"}"]}
\ No newline at end of file
diff --git a/programs/index.js b/programs/index.js
index 8c9e40cb2ad713129dee01326849e9f586a2ea48..219e0fa654e81c239c8df8bc8c0ba10493c80a24 100644
--- a/programs/index.js
+++ b/programs/index.js
@@ -1,6 +1,7 @@
 program_label('frep')
 program_menu('   gears','programs/frep/gears')
 program_menu('   lattice torus','programs/frep/lattice%20torus')
+program_menu('   smiley','programs/frep/smiley')
 program_label('image')
 program_menu('   function','programs/image/function')
 program_menu('   motion detect','programs/image/motion%20detect')