Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
M
mods
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
pub
mods
Commits
717bb43d
Commit
717bb43d
authored
3 years ago
by
Neil Gershenfeld
Browse files
Options
Downloads
Patches
Plain Diff
fix y bug
parent
019d6aa0
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
programs/machines/Roland/mill/SRM-20/mill 3D stl
+1
-1
1 addition, 1 deletion
programs/machines/Roland/mill/SRM-20/mill 3D stl
programs/machines/ShopBot/mill 3D stl
+1
-1
1 addition, 1 deletion
programs/machines/ShopBot/mill 3D stl
with
2 additions
and
2 deletions
programs/machines/Roland/mill/SRM-20/mill 3D stl
+
1
−
1
View file @
717bb43d
{"modules":{"0.0622871075904039":{"definition":"//\n// read stl\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 = 'read STL'\n//\n// initialization\n//\nvar init = function() {\n }\n//\n// inputs\n//\nvar inputs = {\n }\n//\n// outputs\n//\nvar outputs = {\n mesh:{type:'STL',\n event:function(buffer){\n mods.output(mod,'mesh',buffer)}}\n }\n//\n// interface\n//\nvar interface = function(div){\n mod.div = div\n //\n // file input control\n //\n var file = document.createElement('input')\n file.setAttribute('type','file')\n file.setAttribute('id',div.id+'file_input')\n file.style.position = 'absolute'\n file.style.left = 0\n file.style.top = 0\n file.style.width = 0\n file.style.height = 0\n file.style.opacity = 0\n file.addEventListener('change',function() {\n stl_read_handler()\n })\n div.appendChild(file)\n mod.file = file\n //\n // 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 // file select 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('select stl file'))\n btn.addEventListener('click',function(){\n var file = document.getElementById(div.id+'file_input')\n file.value = null\n file.click()\n })\n div.appendChild(btn)\n div.appendChild(document.createElement('br'))\n //\n // info\n //\n var info = document.createElement('div')\n info.setAttribute('id',div.id+'info')\n var text = document.createTextNode('name: ')\n info.appendChild(text)\n mod.namen = text\n info.appendChild(document.createElement('br'))\n var text = document.createTextNode('size: ')\n info.appendChild(text)\n mod.sizen = text\n info.appendChild(document.createElement('br'))\n var text = document.createTextNode('triangles: ')\n info.appendChild(text)\n mod.trianglesn = text\n info.appendChild(document.createElement('br'))\n var text = document.createTextNode('dx: ')\n info.appendChild(text)\n mod.dxn = text\n info.appendChild(document.createElement('br'))\n var text = document.createTextNode('dy: ')\n info.appendChild(text)\n mod.dyn = text\n info.appendChild(document.createElement('br'))\n var text = document.createTextNode('dz: ')\n info.appendChild(text)\n mod.dzn = text\n div.appendChild(info)\n }\n//\n// local functions\n//\n// read handler\n//\nfunction stl_read_handler(event) {\n var file_reader = new FileReader()\n file_reader.onload = stl_load_handler\n input_file = mod.file.files[0]\n file_name = input_file.name\n mod.namen.nodeValue = 'name: '+file_name\n file_reader.readAsArrayBuffer(input_file)\n }\n//\n// load handler\n//\nfunction stl_load_handler(event) {\n //\n // check for binary STL\n //\n var endian = true\n var view = new DataView(event.target.result)\n var triangles = view.getUint32(80,endian)\n var size = 80+4+triangles*(4*12+2)\n if (size != view.byteLength) {\n mod.sizen.nodeValue = 'error: not binary STL'\n mod.trianglesn.nodeValue = ''\n mod.dxn.nodeValue = ''\n mod.dyn.nodeValue = ''\n mod.dzn.nodeValue = ''\n return\n }\n mod.sizen.nodeValue = 'size: '+size\n mod.trianglesn.nodeValue = 'triangles: '+triangles\n //\n // find limits and draw\n //\n var blob = new Blob(['('+draw_limits_worker.toString()+'())'])\n var url = window.URL.createObjectURL(blob)\n var webworker = new Worker(url)\n webworker.addEventListener('message',function(evt) {\n //\n // worker response\n //\n window.URL.revokeObjectURL(url)\n //\n // size\n //\n mod.dxn.nodeValue = 'dx: '+evt.data.dx.toFixed(3)\n mod.dyn.nodeValue = 'dy: '+evt.data.dy.toFixed(3)\n mod.dzn.nodeValue = 'dz: '+evt.data.dz.toFixed(3)\n //\n // image\n //\n var image = evt.data.image\n var height = mod.canvas.height\n var width = mod.canvas.width\n var buffer = new Uint8ClampedArray(evt.data.image)\n var imgdata = new ImageData(buffer,width,height)\n var ctx = mod.canvas.getContext(\"2d\")\n ctx.putImageData(imgdata,0,0)\n //\n // output\n //\n outputs.mesh.event(evt.data.mesh)\n })\n var ctx = mod.canvas.getContext(\"2d\")\n ctx.clearRect(0,0,mod.canvas.width,mod.canvas.height)\n var img = ctx.getImageData(0,0,mod.canvas.width,mod.canvas.height)\n //\n // call worker\n //\n webworker.postMessage({\n height:mod.canvas.height,width:mod.canvas.width,\n image:img.data.buffer,mesh:event.target.result},\n [img.data.buffer,event.target.result])\n }\nfunction draw_limits_worker() {\n self.addEventListener('message',function(evt) {\n //\n // function to draw line\n //\n function line(x0,y0,x1,y1) {\n var ix0 = Math.floor(xo+xw*(x0-xmin)/dx)\n var iy0 = Math.floor(yo+yh*(ymax-y0)/dy)\n var ix1 = Math.floor(xo+xw*(x1-xmin)/dx)\n var iy1 = Math.floor(yo+yh*(ymax-y1)/dy)\n var row,col\n var idx = ix1-ix0\n var idy = iy1-iy0\n if (Math.abs(idy) > Math.abs(idx)) {\n (idy > 0) ?\n (row0=iy0,col0=ix0,row1=iy1,col1=ix1):\n (row0=iy1,col0=ix1,row1=iy0,col1=ix0)\n for (row = row0; row <= row1; ++row) {\n col = Math.floor(col0+(col1-col0)*(row-row0)/(row1-row0))\n image[row*width*4+col*4+0] = 0\n image[row*width*4+col*4+1] = 0\n image[row*width*4+col*4+2] = 0\n image[row*width*4+col*4+3] = 255\n }\n }\n else if ((Math.abs(idx) >= Math.abs(idy)) && (idx != 0)) {\n (idx > 0) ?\n (row0=iy0,col0=ix0,row1=iy1,col1=ix1):\n (row0=iy1,col0=ix1,row1=iy0,col1=ix0)\n for (col = col0; col <= col1; ++col) {\n row = Math.floor(row0+(row1-row0)*(col-col0)/(col1-col0))\n image[row*width*4+col*4+0] = 0\n image[row*width*4+col*4+1] = 0\n image[row*width*4+col*4+2] = 0\n image[row*width*4+col*4+3] = 255\n }\n }\n else {\n row = iy0\n col = ix0\n image[row*width*4+col*4+0] = 0\n image[row*width*4+col*4+1] = 0\n image[row*width*4+col*4+2] = 0\n image[row*width*4+col*4+3] = 255\n }\n }\n //\n // get variables\n //\n var height = evt.data.height\n var width = evt.data.width\n var endian = true\n var image = new Uint8ClampedArray(evt.data.image)\n var view = new DataView(evt.data.mesh)\n var triangles = view.getUint32(80,endian)\n //\n // find limits\n //\n var offset = 80+4\n var x0,x1,x2,y0,y1,y2,z0,z1,z2\n var xmin = Number.MAX_VALUE\n var xmax = -Number.MAX_VALUE\n var ymin = Number.MAX_VALUE\n var ymax = -Number.MAX_VALUE\n var zmin = Number.MAX_VALUE\n var zmax = -Number.MAX_VALUE\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n if (x0 > xmax) xmax = x0\n if (x0 < xmin) xmin = x0\n y0 = view.getFloat32(offset,endian)\n offset += 4\n if (y0 > ymax) ymax = y0\n if (y0 < ymin) ymin = y0\n z0 = view.getFloat32(offset,endian)\n offset += 4\n if (z0 > zmax) zmax = z0\n if (z0 < zmin) zmin = z0\n x1 = view.getFloat32(offset,endian)\n offset += 4\n if (x1 > xmax) xmax = x1\n if (x1 < xmin) xmin = x1\n y1 = view.getFloat32(offset,endian)\n offset += 4\n if (y1 > ymax) ymax = y1\n if (y1 < ymin) ymin = y1\n z1 = view.getFloat32(offset,endian)\n offset += 4\n if (z1 > zmax) zmax = z1\n if (z1 < zmin) zmin = z1\n x2 = view.getFloat32(offset,endian)\n offset += 4\n if (x2 > xmax) xmax = x2\n if (x2 < xmin) xmin = x2\n y2 = view.getFloat32(offset,endian)\n offset += 4\n if (y2 > ymax) ymax = y2\n if (y2 < ymin) ymin = y2\n z2 = view.getFloat32(offset,endian)\n offset += 4\n if (z2 > zmax) zmax = z2\n if (z2 < zmin) zmin = z2\n offset += 2\n }\n var dx = xmax-xmin\n var dy = ymax-ymin\n var dz = zmax-zmin\n //\n // draw mesh\n //\n if (dx > dy) {\n var xo = 0\n var yo = height*.5*(1-dy/dx)\n var xw = width-1\n var yh = (width-1)*dy/dx\n }\n else {\n var xo = width*.5*(1-dx/dy)\n var yo = 0\n var xw = (height-1)*dx/dy\n var yh = height-1\n }\n offset = 80+4\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n y0 = view.getFloat32(offset,endian)\n offset += 4\n z0 = view.getFloat32(offset,endian)\n offset += 4\n x1 = view.getFloat32(offset,endian)\n offset += 4\n y1 = view.getFloat32(offset,endian)\n offset += 4\n z1 = view.getFloat32(offset,endian)\n offset += 4\n x2 = view.getFloat32(offset,endian)\n offset += 4\n y2 = view.getFloat32(offset,endian)\n offset += 4\n z2 = view.getFloat32(offset,endian)\n offset += 4\n offset += 2\n line(x0,y0,x1,y1)\n line(x1,y1,x2,y2)\n line(x2,y2,x0,y0)\n }\n //\n // return results and close\n //\n self.postMessage({\n dx:dx,dy:dy,dz:dz,\n image:evt.data.image,mesh:evt.data.mesh},[evt.data.image,evt.data.mesh])\n self.close()\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":"121.4689005070139","left":"231.1238074852728","filename":"undefined","inputs":{},"outputs":{}},"0.908940842104825":{"definition":"//\n// mesh rotate\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 = 'mesh rotate'\n//\n// initialization\n//\nvar init = function() {\n mod.rx.value = '0'\n mod.ry.value = '0'\n mod.rz.value = '0'\n }\n//\n// inputs\n//\nvar inputs = {\n mesh:{type:'STL',\n event:function(evt){\n mod.mesh = evt.detail\n rotate_mesh()}}}\n//\n// outputs\n//\nvar outputs = {\n mesh:{type:'STL',\n event:function(buffer){\n mods.output(mod,'mesh',buffer)}}}\n//\n// interface\n//\nvar interface = function(div){\n mod.div = div\n //\n // 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 // rotation\n //\n div.appendChild(document.createTextNode('rotation (degrees):'))\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode(' x: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('change',function(){\n rotate_mesh()\n })\n div.appendChild(input)\n mod.rx = input\n div.appendChild(document.createTextNode(' y: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('change',function(){\n rotate_mesh()\n })\n div.appendChild(input)\n mod.ry = input\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode(' z: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('change',function(){\n rotate_mesh()\n })\n div.appendChild(input)\n mod.rz = input\n div.appendChild(document.createTextNode(' (enter)'))\n div.appendChild(document.createElement('br'))\n //\n // info\n //\n var text = document.createTextNode('dx:')\n div.appendChild(text)\n mod.dxn = text\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('dy:')\n div.appendChild(text)\n mod.dyn = text\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('dz:')\n div.appendChild(text)\n mod.dzn = text\n div.appendChild(document.createElement('br'))\n }\n//\n// local functions\n//\n// rotate mesh\n//\nfunction rotate_mesh() {\n //\n // check for binary STL\n //\n var endian = true\n var view = new DataView(mod.mesh)\n var triangles = view.getUint32(80,endian)\n var size = 80+4+triangles*(4*12+2)\n //\n // find limits, rotate, and draw\n //\n var blob = new Blob(['('+rotate_mesh_worker.toString()+'())'])\n var url = window.URL.createObjectURL(blob)\n var webworker = new Worker(url)\n webworker.addEventListener('message',function(evt) {\n //\n // worker response\n //\n window.URL.revokeObjectURL(url)\n //\n // size\n //\n mod.dxn.nodeValue = 'dx: '+evt.data.dx.toFixed(3)\n mod.dyn.nodeValue = 'dy: '+evt.data.dy.toFixed(3)\n mod.dzn.nodeValue = 'dz: '+evt.data.dz.toFixed(3)\n //\n // image\n //\n var image = evt.data.image\n var height = mod.canvas.height\n var width = mod.canvas.width\n var buffer = new Uint8ClampedArray(evt.data.image)\n var imgdata = new ImageData(buffer,width,height)\n var ctx = mod.canvas.getContext(\"2d\")\n ctx.putImageData(imgdata,0,0)\n //\n // mesh\n //\n mod.mesh = evt.data.mesh\n //\n // output\n //\n outputs.mesh.event(evt.data.rotate)\n })\n //\n // call worker\n //\n var ctx = mod.canvas.getContext(\"2d\")\n ctx.clearRect(0,0,mod.canvas.width,mod.canvas.height)\n var img = ctx.getImageData(0,0,mod.canvas.width,mod.canvas.height)\n var rx = parseFloat(mod.rx.value)*Math.PI/180\n var ry = parseFloat(mod.ry.value)*Math.PI/180\n var rz = parseFloat(mod.rz.value)*Math.PI/180\n webworker.postMessage({\n height:mod.canvas.height,width:mod.canvas.width,\n rx:rx,ry:ry,rz:rz,\n image:img.data.buffer,mesh:mod.mesh},\n [img.data.buffer,mod.mesh])\n }\nfunction rotate_mesh_worker() {\n self.addEventListener('message',function(evt) {\n //\n // function to draw line\n //\n function line(x0,y0,x1,y1) {\n var ix0 = Math.floor(xo+xw*(x0-xmin)/dx)\n var iy0 = Math.floor(yo+yh*(ymax-y0)/dy)\n var ix1 = Math.floor(xo+xw*(x1-xmin)/dx)\n var iy1 = Math.floor(yo+yh*(ymax-y1)/dy)\n var row,col\n var idx = ix1-ix0\n var idy = iy1-iy0\n if (Math.abs(idy) > Math.abs(idx)) {\n (idy > 0) ?\n (row0=iy0,col0=ix0,row1=iy1,col1=ix1):\n (row0=iy1,col0=ix1,row1=iy0,col1=ix0)\n for (row = row0; row <= row1; ++row) {\n col = Math.floor(col0+(col1-col0)*(row-row0)/(row1-row0))\n image[row*width*4+col*4+0] = 0\n image[row*width*4+col*4+1] = 0\n image[row*width*4+col*4+2] = 0\n image[row*width*4+col*4+3] = 255\n }\n }\n else if ((Math.abs(idx) >= Math.abs(idy)) && (idx != 0)) {\n (idx > 0) ?\n (row0=iy0,col0=ix0,row1=iy1,col1=ix1):\n (row0=iy1,col0=ix1,row1=iy0,col1=ix0)\n for (col = col0; col <= col1; ++col) {\n row = Math.floor(row0+(row1-row0)*(col-col0)/(col1-col0))\n image[row*width*4+col*4+0] = 0\n image[row*width*4+col*4+1] = 0\n image[row*width*4+col*4+2] = 0\n image[row*width*4+col*4+3] = 255\n }\n }\n else {\n row = iy0\n col = ix0\n image[row*width*4+col*4+0] = 0\n image[row*width*4+col*4+1] = 0\n image[row*width*4+col*4+2] = 0\n image[row*width*4+col*4+3] = 255\n }\n }\n //\n // function to rotate point\n //\n function rotate(x,y,z) {\n var x1 = x\n var y1 = Math.cos(rx)*y-Math.sin(rx)*z\n var z1 = Math.sin(rx)*y+Math.cos(rx)*z\n var x2 = Math.cos(ry)*x1-Math.sin(ry)*z1\n var y2 = y1\n var z2 = Math.sin(ry)*x1+Math.cos(ry)*z1\n var x3 = Math.cos(rz)*x2-Math.sin(rz)*y2\n var y3 = Math.sin(rz)*x2+Math.cos(rz)*y2\n var z3 = z2\n //return([x3,y3,z3])\n return({x:x3,y:y3,z:z3})\n }\n //\n // get variables\n //\n var height = evt.data.height\n var width = evt.data.width\n var rx = evt.data.rx\n var ry = evt.data.ry\n var rz = evt.data.rz\n var endian = true\n var image = new Uint8ClampedArray(evt.data.image)\n var view = new DataView(evt.data.mesh)\n var triangles = view.getUint32(80,endian)\n //\n // find limits\n //\n var offset = 80+4\n var x0,x1,x2,y0,y1,y2,z0,z1,z2\n var xmin = Number.MAX_VALUE\n var xmax = -Number.MAX_VALUE\n var ymin = Number.MAX_VALUE\n var ymax = -Number.MAX_VALUE\n var zmin = Number.MAX_VALUE\n var zmax = -Number.MAX_VALUE\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n y0 = view.getFloat32(offset,endian)\n offset += 4\n z0 = view.getFloat32(offset,endian)\n offset += 4\n x1 = view.getFloat32(offset,endian)\n offset += 4\n y1 = view.getFloat32(offset,endian)\n offset += 4\n z1 = view.getFloat32(offset,endian)\n offset += 4\n x2 = view.getFloat32(offset,endian)\n offset += 4\n y2 = view.getFloat32(offset,endian)\n offset += 4\n z2 = view.getFloat32(offset,endian)\n offset += 4\n offset += 2\n var p0 = rotate(x0,y0,z0)\n if (p0.x > xmax) xmax = p0.x\n if (p0.x < xmin) xmin = p0.x\n if (p0.y > ymax) ymax = p0.y\n if (p0.y < ymin) ymin = p0.y\n if (p0.z > zmax) zmax = p0.z\n if (p0.z < zmin) zmin = p0.z\n var p1 = rotate(x1,y1,z1)\n if (p1.x > xmax) xmax = p1.x\n if (p1.x < xmin) xmin = p1.x\n if (p1.y > ymax) ymax = p1.y\n if (p1.y < ymin) ymin = p1.y\n if (p1.z > zmax) zmax = p1.z\n if (p1.z < zmin) zmin = p1.z\n var p2 = rotate(x2,y2,z2)\n if (p2.x > xmax) xmax = p2.x\n if (p2.x < xmin) xmin = p2.x\n if (p2.y > ymax) ymax = p2.y\n if (p2.y < ymin) ymin = p2.y\n if (p2.z > zmax) zmax = p2.z\n if (p2.z < zmin) zmin = p2.z\n }\n var dx = xmax-xmin\n var dy = ymax-ymin\n var dz = zmax-zmin\n //\n // copy mesh\n //\n var newbuf = evt.data.mesh.slice(0)\n var newview = new DataView(newbuf)\n //\n // copy and draw mesh\n //\n if (dx > dy) {\n var xo = 0\n var yo = height*.5*(1-dy/dx)\n var xw = (width-1)\n var yh = (width-1)*dy/dx\n }\n else {\n var xo = width*.5*(1-dx/dy)\n var yo = 0\n var xw = (height-1)*dx/dy\n var yh = (height-1)\n }\n offset = 80+4\n var newoffset = 80+4\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n y0 = view.getFloat32(offset,endian)\n offset += 4\n z0 = view.getFloat32(offset,endian)\n offset += 4\n x1 = view.getFloat32(offset,endian)\n offset += 4\n y1 = view.getFloat32(offset,endian)\n offset += 4\n z1 = view.getFloat32(offset,endian)\n offset += 4\n x2 = view.getFloat32(offset,endian)\n offset += 4\n y2 = view.getFloat32(offset,endian)\n offset += 4\n z2 = view.getFloat32(offset,endian)\n offset += 4\n offset += 2\n var p0 = rotate(x0,y0,z0)\n var p1 = rotate(x1,y1,z1)\n var p2 = rotate(x2,y2,z2)\n line(p0.x,p0.y,p1.x,p1.y)\n line(p1.x,p1.y,p2.x,p2.y)\n line(p2.x,p2.y,p0.x,p0.y)\n newoffset += 3*4\n newview.setFloat32(newoffset,p0.x,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p0.y,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p0.z,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p1.x,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p1.y,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p1.z,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p2.x,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p2.y,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p2.z,endian)\n newoffset += 4\n newoffset += 2\n }\n //\n // return results and close\n //\n self.postMessage({\n dx:dx,dy:dy,dz:dz,\n image:evt.data.image,mesh:evt.data.mesh,rotate:newbuf},\n [evt.data.image,evt.data.mesh,newbuf])\n self.close()\n })\n }\nfunction old_rotate_mesh() {\n //\n // function to rotate point\n //\n function rotate(x,y,z) {\n var x1 = x\n var y1 = Math.cos(rx)*y-Math.sin(rx)*z\n var z1 = Math.sin(rx)*y+Math.cos(rx)*z\n var x2 = Math.cos(ry)*x1-Math.sin(ry)*z1\n var y2 = y1\n var z2 = Math.sin(ry)*x1+Math.cos(ry)*z1\n var x3 = Math.cos(rz)*x2-Math.sin(rz)*y2\n var y3 = Math.sin(rz)*x2+Math.cos(rz)*y2\n var z3 = z2\n return([x3,y3,z3])\n }\n //\n // get vars\n //\n var view = mod.mesh\n var endian = true\n var triangles = view.getUint32(80,endian)\n mod.triangles = triangles\n var size = 80+4+triangles*(4*12+2)\n var rx = parseFloat(mod.rx.value)*Math.PI/180\n var ry = parseFloat(mod.ry.value)*Math.PI/180\n var rz = parseFloat(mod.rz.value)*Math.PI/180\n //\n // find limits\n //\n var offset = 80+4\n var x0,x1,x2,y0,y1,y2,z0,z1,z2\n var xmin = Number.MAX_VALUE\n var xmax = -Number.MAX_VALUE\n var ymin = Number.MAX_VALUE\n var ymax = -Number.MAX_VALUE\n var zmin = Number.MAX_VALUE\n var zmax = -Number.MAX_VALUE\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n y0 = view.getFloat32(offset,endian)\n offset += 4\n z0 = view.getFloat32(offset,endian)\n offset += 4\n x1 = view.getFloat32(offset,endian)\n offset += 4\n y1 = view.getFloat32(offset,endian)\n offset += 4\n z1 = view.getFloat32(offset,endian)\n offset += 4\n x2 = view.getFloat32(offset,endian)\n offset += 4\n y2 = view.getFloat32(offset,endian)\n offset += 4\n z2 = view.getFloat32(offset,endian)\n offset += 4\n offset += 2\n var p0 = rotate(x0,y0,z0)\n if (p0[0] > xmax) xmax = p0[0]\n if (p0[0] < xmin) xmin = p0[0]\n if (p0[1] > ymax) ymax = p0[1]\n if (p0[1] < ymin) ymin = p0[1]\n if (p0[2] > zmax) zmax = p0[2]\n if (p0[2] < zmin) zmin = p0[2]\n var p1 = rotate(x1,y1,z1)\n if (p1[0] > xmax) xmax = p1[0]\n if (p1[0] < xmin) xmin = p1[0]\n if (p1[1] > ymax) ymax = p1[1]\n if (p1[1] < ymin) ymin = p1[1]\n if (p1[2] > zmax) zmax = p1[2]\n if (p1[2] < zmin) zmin = p1[2]\n var p2 = rotate(x2,y2,z2)\n if (p2[0] > xmax) xmax = p2[0]\n if (p2[0] < xmin) xmin = p2[0]\n if (p2[1] > ymax) ymax = p2[1]\n if (p2[1] < ymin) ymin = p2[1]\n if (p2[2] > zmax) zmax = p2[2]\n if (p2[2] < zmin) zmin = p2[2]\n }\n mod.dx = xmax-xmin\n mod.dy = ymax-ymin\n mod.dz = zmax-zmin\n mod.dxn.nodeValue = 'dx: '+mod.dx.toFixed(3)\n mod.dyn.nodeValue = 'dy: '+mod.dy.toFixed(3)\n mod.dzn.nodeValue = 'dz: '+mod.dz.toFixed(3)\n mod.xmin = xmin\n mod.ymin = ymin\n mod.zmin = zmin\n mod.xmax = xmax\n mod.ymax = ymax\n mod.zmax = zmax\n //\n // copy mesh\n //\n var buf = mod.mesh.buffer.slice(0)\n var newview = new DataView(buf)\n //\n // draw projection and save rotation\n //\n var ctx = mod.meshcanvas.getContext('2d')\n var w = mod.meshcanvas.width\n var h = mod.meshcanvas.height\n ctx.clearRect(0,0,w,h)\n var dx = mod.dx\n var dy = mod.dy\n if (dx > dy) {\n var xo = 0\n var yo = h*.5*(1-dy/dx)\n var xw = w\n var yh = w*dy/dx\n }\n else {\n var xo = w*.5*(1-dx/dy)\n var yo = 0\n var xw = h*dx/dy\n var yh = h\n }\n ctx.beginPath()\n offset = 80+4\n var newoffset = 80+4\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n y0 = view.getFloat32(offset,endian)\n offset += 4\n z0 = view.getFloat32(offset,endian)\n offset += 4\n x1 = view.getFloat32(offset,endian)\n offset += 4\n y1 = view.getFloat32(offset,endian)\n offset += 4\n z1 = view.getFloat32(offset,endian)\n offset += 4\n x2 = view.getFloat32(offset,endian)\n offset += 4\n y2 = view.getFloat32(offset,endian)\n offset += 4\n z2 = view.getFloat32(offset,endian)\n offset += 4\n offset += 2\n var p0 = rotate(x0,y0,z0)\n var p1 = rotate(x1,y1,z1)\n var p2 = rotate(x2,y2,z2)\n x0 = xo+xw*(p0[0]-xmin)/dx\n y0 = yo+yh*(ymax-p0[1])/dy\n x1 = xo+xw*(p1[0]-xmin)/dx\n y1 = yo+yh*(ymax-p1[1])/dy\n x2 = xo+xw*(p2[0]-xmin)/dx\n y2 = yo+yh*(ymax-p2[1])/dy\n ctx.moveTo(x0,y0)\n ctx.lineTo(x1,y1)\n ctx.lineTo(x2,y2)\n ctx.lineTo(x0,y0)\n newoffset += 3*4\n newview.setFloat32(newoffset,p0[0],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p0[1],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p0[2],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p1[0],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p1[1],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p1[2],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p2[0],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p2[1],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p2[2],endian)\n newoffset += 4\n newoffset += 2\n }\n ctx.stroke()\n //\n // generate output\n //\n outputs.mesh.event(buf)\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":"252.46890050701393","left":"694.1238074852727","filename":"undefined","inputs":{},"outputs":{}},"0.373975449262817":{"definition":"//\n// mesh height map\n// \n// Neil Gershenfeld 1/16/20\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 = 'mesh height map'\n//\n// initialization\n//\nvar init = function() {\n mod.mmunits.value = '25.4'\n mod.inunits.value = '1'\n mod.width.value = '1000'\n mod.border.value = '0'\n }\n//\n// inputs\n//\nvar inputs = {\n mesh:{type:'STL',\n event:function(evt){\n mod.mesh = new DataView(evt.detail)\n find_limits_map()}}}\n//\n// outputs\n//\nvar outputs = {\n map:{type:'',label:'height map',\n event:function(heightmap){\n var obj = {}\n obj.map = heightmap\n obj.xmin = mod.xmin\n obj.xmax = mod.xmax\n obj.ymin = mod.ymin\n obj.ymax = mod.ymax\n obj.zmin = mod.zmin\n obj.zmax = mod.zmax\n obj.width = mod.img.width\n obj.height = mod.img.height\n obj.mmunits = mod.mmunits.value\n mods.output(mod,'map',obj)\n }}}\n//\n// interface\n//\nvar interface = function(div){\n mod.div = div\n //\n // on-screen height map canvas\n //\n div.appendChild(document.createTextNode(' '))\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.mapcanvas = 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 // mesh units\n //\n div.appendChild(document.createTextNode('mesh units: (enter)'))\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode('mm: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('change',function(){\n mod.inunits.value = parseFloat(mod.mmunits.value)/25.4\n find_limits_map()\n })\n div.appendChild(input)\n mod.mmunits = input\n div.appendChild(document.createTextNode(' in: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('change',function(){\n mod.mmunits.value = parseFloat(mod.inunits.value)*25.4\n find_limits_map()\n })\n div.appendChild(input)\n mod.inunits = input\n //\n // mesh size\n //\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode('mesh size:'))\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('XxYxZ (units)')\n div.appendChild(text)\n mod.meshsize = text\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('XxYxZ (mm)')\n div.appendChild(text)\n mod.mmsize = text\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('XxYxZ (in)')\n div.appendChild(text)\n mod.insize = text\n //\n // height map border \n //\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode('border: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('change',function(){\n find_limits_map()\n })\n div.appendChild(input)\n mod.border = input\n div.appendChild(document.createTextNode(' (units)'))\n //\n // height map width\n //\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode('width: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('change',function(){\n find_limits_map()\n })\n div.appendChild(input)\n mod.width = input\n div.appendChild(document.createTextNode(' (pixels)'))\n //\n // view height map\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 btn.appendChild(document.createTextNode('view height map'))\n btn.addEventListener('click',function(){\n var win = window.open('')\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 })\n win.document.body.appendChild(btn)\n win.document.body.appendChild(document.createElement('br'))\n var canvas = document.createElement('canvas')\n canvas.width = mod.img.width\n canvas.height = mod.img.height\n win.document.body.appendChild(canvas)\n var ctx = canvas.getContext(\"2d\")\n ctx.drawImage(mod.img,0,0)\n })\n div.appendChild(btn)\n }\n//\n// local functions\n//\n// find limits then map \n//\nfunction find_limits_map() {\n var blob = new Blob(['('+limits_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 mod.triangles = evt.data.triangles\n mod.xmin = evt.data.xmin\n mod.xmax = evt.data.xmax\n mod.ymin = evt.data.ymin\n mod.ymax = evt.data.ymax\n mod.zmin = evt.data.zmin\n mod.zmax = evt.data.zmax\n mod.dx = mod.xmax-mod.xmin\n mod.dy = mod.ymax-mod.ymin\n mod.dz = mod.zmax-mod.zmin\n mod.meshsize.nodeValue = \n mod.dx.toFixed(3)+' x '+\n mod.dy.toFixed(3)+' x '+\n mod.dz.toFixed(3)+' (units)'\n var mm = parseFloat(mod.mmunits.value)\n mod.mmsize.nodeValue = \n (mod.dx*mm).toFixed(3)+' x '+\n (mod.dy*mm).toFixed(3)+' x '+\n (mod.dz*mm).toFixed(3)+' (mm)'\n var inches = parseFloat(mod.inunits.value)\n mod.insize.nodeValue = \n (mod.dx*inches).toFixed(3)+' x '+\n (mod.dy*inches).toFixed(3)+' x '+\n (mod.dz*inches).toFixed(3)+' (in)'\n mods.fit(mod.div)\n map_mesh()\n })\n var border = parseFloat(mod.border.value)\n webworker.postMessage({\n mesh:mod.mesh,\n border:border})\n }\nfunction limits_worker() {\n self.addEventListener('message',function(evt) {\n var view = evt.data.mesh\n var border = evt.data.border\n //\n // get vars\n //\n var endian = true\n var triangles = view.getUint32(80,endian)\n var size = 80+4+triangles*(4*12+2)\n //\n // find limits\n //\n var offset = 80+4\n var x0,x1,x2,y0,y1,y2,z0,z1,z2\n var xmin = Number.MAX_VALUE\n var xmax = -Number.MAX_VALUE\n var ymin = Number.MAX_VALUE\n var ymax = -Number.MAX_VALUE\n var zmin = Number.MAX_VALUE\n var zmax = -Number.MAX_VALUE\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n y0 = view.getFloat32(offset,endian)\n offset += 4\n z0 = view.getFloat32(offset,endian)\n offset += 4\n x1 = view.getFloat32(offset,endian)\n offset += 4\n y1 = view.getFloat32(offset,endian)\n offset += 4\n z1 = view.getFloat32(offset,endian)\n offset += 4\n x2 = view.getFloat32(offset,endian)\n offset += 4\n y2 = view.getFloat32(offset,endian)\n offset += 4\n z2 = view.getFloat32(offset,endian)\n offset += 4\n offset += 2\n if (x0 > xmax) xmax = x0\n if (x0 < xmin) xmin = x0\n if (y0 > ymax) ymax = y0\n if (y0 < ymin) ymin = y0\n if (z0 > zmax) zmax = z0\n if (z0 < zmin) zmin = z0\n if (x1 > xmax) xmax = x1\n if (x1 < xmin) xmin = x1\n if (y1 > ymax) ymax = y1\n if (y1 < ymin) ymin = y1\n if (z1 > zmax) zmax = z1\n if (z1 < zmin) zmin = z1\n if (x2 > xmax) xmax = x2\n if (x2 < xmin) xmin = x2\n if (y2 > ymax) ymax = y2\n if (y2 < ymin) ymin = y2\n if (z2 > zmax) zmax = z2\n if (z2 < zmin) zmin = z2\n }\n xmin -= border\n xmax += border\n ymin -= border\n ymax += border\n //\n // return\n //\n self.postMessage({triangles:triangles,\n xmin:xmin,xmax:xmax,ymin:ymin,ymax:ymax,\n zmin:zmin,zmax:zmax})\n self.close()\n })\n }\n//\n// map mesh\n// \nfunction map_mesh() {\n var blob = new Blob(['('+map_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.imgbuffer)\n var map = new Float32Array(evt.data.mapbuffer)\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.mapcanvas.height*.5*(1-h/w)\n var wd = mod.mapcanvas.width\n var hd = mod.mapcanvas.width*h/w\n }\n else {\n var x0 = mod.mapcanvas.width*.5*(1-w/h)\n var y0 = 0\n var wd = mod.mapcanvas.height*w/h\n var hd = mod.mapcanvas.height\n }\n var ctx = mod.mapcanvas.getContext(\"2d\")\n ctx.clearRect(0,0,mod.mapcanvas.width,mod.mapcanvas.height)\n ctx.drawImage(mod.img,x0,y0,wd,hd)\n outputs.map.event(map)\n })\n var ctx = mod.mapcanvas.getContext(\"2d\")\n ctx.clearRect(0,0,mod.mapcanvas.width,mod.mapcanvas.height)\n mod.img.width = parseInt(mod.width.value)\n mod.img.height = Math.round(mod.img.width*mod.dy/mod.dx)\n var ctx = mod.img.getContext(\"2d\")\n var img = ctx.getImageData(0,0,mod.img.width,mod.img.height)\n var map = new Float32Array(mod.img.width*mod.img.height)\n webworker.postMessage({\n height:mod.img.height,width:mod.img.width,\n imgbuffer:img.data.buffer,\n mapbuffer:map.buffer,\n mesh:mod.mesh,\n xmin:mod.xmin,xmax:mod.xmax,\n ymin:mod.ymin,ymax:mod.ymax,\n zmin:mod.zmin,zmax:mod.zmax},\n [img.data.buffer,map.buffer])\n }\nfunction map_worker() {\n self.addEventListener('message',function(evt) {\n var h = evt.data.height\n var w = evt.data.width\n var view = evt.data.mesh\n var xmin = evt.data.xmin\n var xmax = evt.data.xmax\n var ymin = evt.data.ymin\n var ymax = evt.data.ymax\n var zmin = evt.data.zmin\n var zmax = evt.data.zmax\n var buf = new Uint8ClampedArray(evt.data.imgbuffer)\n var map = new Float32Array(evt.data.mapbuffer)\n //\n // get vars from buffer\n //\n var endian = true\n var triangles = view.getUint32(80,endian)\n var size = 80+4+triangles*(4*12+2)\n //\n // initialize map and image\n //\n for (var row = 0; row < h; ++row) {\n for (var col = 0; col < w; ++col) {\n map[(h-1-row)*w+col] = zmin\n buf[(h-1-row)*w*4+col*4+0] = 0\n buf[(h-1-row)*w*4+col*4+1] = 0\n buf[(h-1-row)*w*4+col*4+2] = 0\n buf[(h-1-row)*w*4+col*4+3] = 255\n }\n }\n //\n // loop over triangles\n //\n var segs = []\n offset = 80+4\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n y0 = view.getFloat32(offset,endian)\n offset += 4\n z0 = view.getFloat32(offset,endian)\n offset += 4\n x1 = view.getFloat32(offset,endian)\n offset += 4\n y1 = view.getFloat32(offset,endian)\n offset += 4\n z1 = view.getFloat32(offset,endian)\n offset += 4\n x2 = view.getFloat32(offset,endian)\n offset += 4\n y2 = view.getFloat32(offset,endian)\n offset += 4\n z2 = view.getFloat32(offset,endian)\n offset += 4\n offset += 2\n //\n // check normal if needs to be drawn\n //\n if (((x1-x0)*(y1-y2)-(x1-x2)*(y1-y0)) >= 0)\n continue\n //\n // quantize image coordinates\n //\n x0 = Math.floor((w-1)*(x0-xmin)/(xmax-xmin))\n x1 = Math.floor((w-1)*(x1-xmin)/(xmax-xmin))\n x2 = Math.floor((w-1)*(x2-xmin)/(xmax-xmin))\n y0 = Math.floor((h-1)*(y0-ymin)/(ymax-ymin))\n y1 = Math.floor((h-1)*(y1-ymin)/(ymax-ymin))\n y2 = Math.floor((h-1)*(y2-ymin)/(ymax-ymin))\n //\n // sort projection order\n //\n if (y1 > y2) {\n var temp = x1;\n x1 = x2;\n x2 = temp\n var temp = y1;\n y1 = y2;\n y2 = temp\n var temp = z1;\n z1 = z2;\n z2 = temp\n }\n if (y0 > y1) {\n var temp = x0;\n x0 = x1;\n x1 = temp\n var temp = y0;\n y0 = y1;\n y1 = temp\n var temp = z0;\n z0 = z1;\n z1 = temp\n }\n if (y1 > y2) {\n var temp = x1;\n x1 = x2;\n x2 = temp\n var temp = y1;\n y1 = y2;\n y2 = temp\n var temp = z1;\n z1 = z2;\n z2 = temp\n }\n //\n // check orientation after sort\n //\n if (x1 < (x0+((x2-x0)*(y1-y0))/(y2-y0)))\n var dir = 1;\n else\n var dir = -1;\n //\n // set z values\n //\n if (y2 != y1) {\n for (var y = y1; y <= y2; ++y) {\n x12 = Math.floor(0.5+x1+(y-y1)*(x2-x1)/(y2-y1))\n z12 = z1+(y-y1)*(z2-z1)/(y2-y1)\n x02 = Math.floor(0.5+x0+(y-y0)*(x2-x0)/(y2-y0))\n z02 = z0+(y-y0)*(z2-z0)/(y2-y0)\n if (x12 != x02)\n var slope = (z02-z12)/(x02-x12)\n else\n var slope = 0\n var x = x12 - dir\n while (x != x02) {\n x += dir\n var z = z12+slope*(x-x12)\n if (z > map[(h-1-y)*w+x]) {\n map[(h-1-y)*w+x] = z\n var iz = Math.floor(255*(z-zmin)/(zmax-zmin))\n buf[(h-1-y)*w*4+x*4+0] = iz\n buf[(h-1-y)*w*4+x*4+1] = iz\n buf[(h-1-y)*w*4+x*4+2] = iz\n }\n }\n }\n }\n if (y1 != y0) {\n for (var y = y0; y <= y1; ++y) {\n x01 = Math.floor(0.5+x0+(y-y0)*(x1-x0)/(y1-y0))\n z01 = z0+(y-y0)*(z1-z0)/(y1-y0)\n x02 = Math.floor(0.5+x0+(y-y0)*(x2-x0)/(y2-y0))\n z02 = z0+(y-y0)*(z2-z0)/(y2-y0)\n if (x01 != x02)\n var slope = (z02-z01)/(x02-x01)\n else\n var slope = 0\n var x = x01 - dir\n while (x != x02) {\n x += dir\n var z = z01+slope*(x-x01)\n if (z > map[(h-1-y)*w+x]) {\n map[(h-1-y)*w+x] = z\n var iz = Math.floor(255*(z-zmin)/(zmax-zmin))\n buf[(h-1-y)*w*4+x*4+0] = iz\n buf[(h-1-y)*w*4+x*4+1] = iz\n buf[(h-1-y)*w*4+x*4+2] = iz\n }\n }\n }\n }\n }\n //\n // output the map\n //\n self.postMessage({imgbuffer:buf.buffer,mapbuffer:map.buffer},[buf.buffer,map.buffer])\n self.close()\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":"124.64802090317082","left":"1209.2725971321183","filename":"undefined","inputs":{},"outputs":{}},"0.21976500984768532":{"definition":"//\n// view path\n//\n// Neil Gershenfeld \n// (c) Massachusetts Institute of Technology 2019\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// todo:\n// erase and update new path\n// show depth info\n// show size\n// calculate camera far\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'view path'\n//\n// initialization\n//\nvar init = function() {\n }\n//\n// inputs\n//\nvar inputs = {\n path:{type:'',\n event:function(evt){\n mod.path = evt.detail.path\n mod.name = evt.detail.name\n mod.dpi = evt.detail.dpi\n mod.width = evt.detail.width\n mod.height = evt.detail.height\n mod.depth = evt.detail.depth\n show_path_info()\n show_path()\n mods.fit(mod.div)\n outputs.path.event()\n }}}\n//\n// outputs\n//\nvar outputs = {\n path:{type:'',\n event:function(){\n cmd = {}\n cmd.path = mod.path\n cmd.name = mod.name\n cmd.dpi = mod.dpi\n cmd.width = mod.width\n cmd.height = mod.height\n mods.output(mod,'path',cmd)\n }}}\n//\n// interface\n//\nvar interface = function(div){\n mod.div = div\n //\n // info\n //\n var text = document.createTextNode('name: ')\n div.appendChild(text)\n mod.nametext = text\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('(mm)')\n div.appendChild(text)\n mod.mmtext = text\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('(in)')\n div.appendChild(text)\n mod.intext = text\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 open_view_window()\n })\n div.appendChild(btn)\n }\n//\n// local functions\n//\n// show_path_info\n//\nfunction show_path_info() {\n mod.nametext.nodeValue = 'name: '+mod.name\n var width = (25.4*mod.width/mod.dpi).toFixed(3)\n var height = (25.4*mod.height/mod.dpi).toFixed(3)\n var depth = (25.4*mod.depth/mod.dpi).toFixed(3)\n if (mod.depth == undefined)\n mod.mmtext.nodeValue = width+' x '+height+' (mm)'\n else\n mod.mmtext.nodeValue = width+' x '+height+' x '+depth+' (mm)'\n var width = (mod.width/mod.dpi).toFixed(3)\n var height = (mod.height/mod.dpi).toFixed(3)\n var depth = (mod.depth/mod.dpi).toFixed(3)\n if (mod.depth == undefined)\n mod.intext.nodeValue = width+' x '+height+' (in)'\n else\n mod.intext.nodeValue = width+' x '+height+' x '+depth+' (in)'\n mods.fit(mod.div)\n }\n//\n// show_path\n//\nfunction show_path() {\n var scene = mod.scene\n var camera = mod.camera\n var renderer = mod.renderer\n //\n // check if view window open\n //\n if (mod.win == undefined) {\n open_view_window()\n return\n }\n //\n // check for path\n //\n if (mod.path == undefined)\n return\n //\n // clear scene, leave camera\n //\n var length = scene.children.length\n for (var c = (length-1); c > 1; --c) {\n scene.remove(scene.children[c])\n }\n //\n // fit camera\n //\n mod.thetaxy = 0\n mod.thetaz = 0\n mod.r = mod.height/2\n mod.x0 = mod.width/2\n mod.y0 = mod.height/2\n camera.position.set(mod.x0,mod.y0,mod.r)\n camera.up = new THREE.Vector3(0,1,0)\n camera.lookAt(new THREE.Vector3(mod.x0,mod.y0,0))\n camera.updateProjectionMatrix()\n //\n // draw segments\n //\n var arrow_size = 1+mod.width/200\n var path = mod.path\n for (var segment = 0; segment < path.length; ++segment) {\n if (segment > 0)\n add_arrow(path[segment-1][path[segment-1].length-1],path[segment][0],0xff0000,arrow_size) \n for (var point = 1; point < path[segment].length; ++point) {\n add_arrow(path[segment][point-1],path[segment][point],0x0000ff,arrow_size)\n }\n }\n //\n // add axes\n //\n var length = mod.height/10\n add_arrow([0,0,0],[length,0,0],0xff0000,arrow_size)\n add_arrow([0,0,0],[0,length,0],0x00ff00,arrow_size)\n add_arrow([0,0,0],[0,0,length],0x0000ff,arrow_size)\n //\n // render\n //\n update()\n //\n // add_arrow\n //\n function add_arrow(start,stop,color,size) {\n var origin = new THREE.Vector3().fromArray(start)\n if (mod.depth == undefined)\n origin.z = 0\n var end = new THREE.Vector3().fromArray(stop)\n if (mod.depth == undefined)\n end.z = 0\n var length = new THREE.Vector3().subVectors(end,origin).length()\n if (length <= size) {\n add_line(origin,end,color)\n //length = 1.1*size\n return\n }\n var direction = new THREE.Vector3().subVectors(end,origin).normalize()\n var arrow = new THREE.ArrowHelper(direction,origin,length,color,size,size)\n scene.add(arrow)\n }\n //\n // add_line\n //\n function add_line(start,stop,colorhex) {\n var geometry = new THREE.Geometry()\n geometry.vertices.push(start,stop)\n var material = new THREE.LineBasicMaterial({color:colorhex})\n var line = new THREE.Line(geometry,material)\n scene.add(line)\n }\n //\n // update\n //\n function update() {\n renderer.render(scene,camera)\n }\n }\n//\n// open_view_window\n//\nfunction open_view_window() {\n //\n // open window\n //\n win = window.open('')\n mod.win = win\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// init_window\n//\nfunction init_window() {\n //document.write('<script type=\"text/javascript\">'+arg+'</script>')\n //document.close()\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 mod.win.close()\n mod.win = undefined\n })\n mod.win.document.body.appendChild(btn)\n //\n // label text\n //\n var text = win.document.createTextNode(' left: pan, right: rotate, scroll: zoom')\n mod.win.document.body.appendChild(text)\n //\n // GL container\n //\n mod.win.document.body.appendChild(document.createElement('br')) \n container = mod.win.document.createElement('div')\n container.style.overflow = 'hidden'\n mod.win.document.body.appendChild(container)\n //\n // event handlers\n //\n container.addEventListener('contextmenu',context_menu)\n container.addEventListener('mousedown',mouse_down)\n container.addEventListener('mouseup',mouse_up)\n container.addEventListener('mousemove',mouse_move)\n container.addEventListener('wheel',mouse_wheel)\n //\n // add scene\n //\n scene = new THREE.Scene()\n mod.scene = scene\n var width = mod.win.innerWidth\n var height = mod.win.innerHeight\n var aspect = width/height\n var near = 0.1\n var far = 1000000\n camera = new THREE.PerspectiveCamera(90,aspect,near,far)\n mod.camera = camera\n scene.add(camera)\n //\n // add renderer\n //\n renderer = new THREE.WebGLRenderer({antialias:true})\n mod.renderer = renderer\n renderer.setClearColor(0xffffff)\n renderer.setSize(width,height)\n container.appendChild(renderer.domElement)\n //\n // show the path if available\n //\n show_path()\n //\n // context_menu\n //\n function context_menu(evt) {\n evt.preventDefault()\n evt.stopPropagation()\n return (false)\n }\n //\n // mouse_down\n //\n function mouse_down(evt) {\n evt.preventDefault()\n evt.stopPropagation()\n mod.button = evt.button\n mod.x = evt.clientX\n mod.y = evt.clientY\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 // mouse_move\n //\n function mouse_move(evt) {\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/mod.win.innerHeight\n -Math.cos(mod.thetaz)*mod.width*dx/mod.win.innerWidth\n mod.y0 += \n Math.cos(mod.thetaz)*mod.height*dy/mod.win.innerHeight\n +Math.sin(mod.thetaz)*mod.width*dx/mod.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 renderer.render(scene,camera)\n }\n else if (mod.button == 2) {\n mod.thetaxy += dy/mod.win.innerHeight\n mod.thetaz += dx/mod.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 if (Math.cos(mod.thetaxy) > 0)\n camera.up = new THREE.Vector3(Math.sin(mod.thetaz),Math.cos(mod.thetaz),0)\n else\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 // mouse_wheel\n //\n function mouse_wheel(evt) {\n evt.preventDefault()\n evt.stopPropagation()\n var dy = evt.deltaY/mod.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 renderer.render(scene,camera)\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":"1051.330989940735","left":"1230.9648592659537","filename":"undefined","inputs":{},"outputs":{}},"0.5958662931535647":{"definition":"//\n// save file\n//\n// Neil Gershenfeld \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// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'save file'\n//\n// initialization\n//\nvar init = function() {\n }\n//\n// inputs\n//\nvar inputs = {\n file:{type:'object',\n event:function(evt){\n mod.name = evt.detail.name\n mod.contents = evt.detail.contents\n save_file()\n }}}\n//\n// outputs\n//\nvar outputs = {}\n//\n// interface\n//\nvar interface = function(div){\n mod.div = div\n //\n // info\n //\n var text = document.createTextNode('name:')\n div.appendChild(text)\n mod.nametext = text\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('size:')\n div.appendChild(text)\n mod.sizetext = text\n div.appendChild(document.createElement('br'))\n }\n//\n// local functions\n//\nfunction save_file() {\n var a = document.createElement('a')\n a.setAttribute('href','data:text/plain;charset=utf-8,'+ \n encodeURIComponent(mod.contents))\n a.setAttribute('download',mod.name)\n a.style.display = 'none'\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n mod.nametext.nodeValue = 'name: '+mod.name\n mods.fit(mod.div)\n mod.sizetext.nodeValue = 'size: '+mod.contents.length\n mods.fit(mod.div)\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":"830.7331133840215","left":"1251.9910798307683","filename":"undefined","inputs":{},"outputs":{}},"0.3062798763523076":{"definition":"//\n// Roland SRM-20 milling machine\n//\n// Neil Gershenfeld\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// closure\n//\n/*\nG-codes:\nG00X10.0\nG90 (absolute positioning)\nG21 (mm units)\n#.0 numbers\nG00 (positioning rapid move)\nG01 (linear motion)\nM03 (start spindle)\nM05 (stop spindle)\nF (feed rate mm/min, 6-1800)\n203.2 (X) x 152.4 (Y) x 60.5 (Z) mm \n*/\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'Roland SRM-20 milling machine'\n//\n// initialization\n//\nvar init = function() {\n mod.units = 100.0\n mod.speed.value = 4\n mod.ox.value = 10\n mod.oy.value = 10\n mod.oz.value = 10\n mod.jz.value = 2\n mod.hx.value = 0\n mod.hy.value = 152.4\n mod.hz.value = 60.5\n }\n//\n// inputs\n//\nvar inputs = {\n path:{type:'',\n event:function(evt){\n mod.name = evt.detail.name\n mod.path = evt.detail.path\n mod.dpi = evt.detail.dpi\n mod.width = evt.detail.width\n mod.height = evt.detail.height\n make_path()\n }}}\n//\n// outputs\n//\nvar outputs = {\n file:{type:'',\n event:function(obj){\n mods.output(mod,'file',obj)\n }}}\n//\n// interface\n//\nvar interface = function(div){\n mod.div = div\n //\n // speed\n //\n div.appendChild(document.createTextNode('speed: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n div.appendChild(input)\n mod.speed = input\n div.appendChild(document.createTextNode(' (mm/s)'))\n div.appendChild(document.createElement('br'))\n //\n // origin\n //\n div.appendChild(document.createTextNode('origin:'))\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode('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.createTextNode(' (mm)'))\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(' (mm)'))\n div.appendChild(document.createElement('br'))\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.createTextNode(' (mm)'))\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('move to origin')\n span.appendChild(text)\n btn.appendChild(span)\n btn.addEventListener('click',function(){\n var x0 = mod.units*parseFloat(mod.ox.value);\n var y0 = mod.units*parseFloat(mod.oy.value);\n var z0 = mod.units*parseFloat(mod.oz.value);\n var zjog = z0+mod.units*parseFloat(mod.jz.value);\n //\n // G-code version\n //\n /*\n str = '%\\n' // data start\n str += 'G90\\n' // absolute units\n str += 'G21\\n' // mm units\n str += 'G00Z30.0\\n' // move z\n str += 'M02\\n' // end of program\n */\n //\n // RML version\n //\n var str = \"PA;PA;VS10;!VZ10;!PZ0,\"+zjog+\";PU\"+x0+\",\"+y0+\";Z\"+x0+\",\"+y0+\",\"+z0+\";!MC0;\"+\"\\u0004\"\n //\n // send command\n //\n var obj = {}\n obj.type = 'command'\n obj.name = mod.name+'.rml'\n obj.contents = str\n outputs.file.event(obj)\n })\n div.appendChild(btn)\n div.appendChild(document.createElement('br'))\n //\n // jog\n //\n div.appendChild(document.createTextNode('jog height:'))\n div.appendChild(document.createElement('br'))\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.jz = input\n div.appendChild(document.createTextNode(' (mm)'))\n div.appendChild(document.createElement('br'))\n //\n // home\n //\n div.appendChild(document.createTextNode('home:'))\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode('x: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n div.appendChild(input)\n mod.hx = input\n div.appendChild(document.createTextNode(' (mm)'))\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.hy = input\n div.appendChild(document.createTextNode(' (mm)'))\n div.appendChild(document.createElement('br'))\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.hz = input\n div.appendChild(document.createTextNode(' (mm)'))\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('move to home')\n span.appendChild(text)\n btn.appendChild(span)\n btn.addEventListener('click',function(){\n var xhome = mod.units*parseFloat(mod.hx.value);\n var yhome = mod.units*parseFloat(mod.hy.value);\n var zhome = mod.units*parseFloat(mod.hz.value);\n //\n // G-code version\n //\n /*\n str = '%\\n' // data start\n str += 'G90\\n' // absolute units\n str += 'G21\\n' // mm units\n str += 'G00Z50.0\\n' // move z\n str += 'M02\\n' // end of program\n */\n //\n // RML version\n //\n var str = \"PA;PA;!PZ0,\"+zhome+\";PU\"+xhome+\",\"+yhome+\";!MC0;\"+\"\\u0004\"\n //\n // send command\n //\n var obj = {}\n obj.type = 'command'\n obj.name = mod.name+'.rml'\n obj.contents = str\n outputs.file.event(obj)\n })\n div.appendChild(btn)\n div.appendChild(document.createElement('br'))\n }\n//\n// local functions\n//\nfunction make_path() {\n var dx = 25.4*mod.width/mod.dpi\n var nx = mod.width\n var speed = parseFloat(mod.speed.value)\n var jog = parseFloat(mod.oz.value)+parseFloat(mod.jz.value)\n var ijog = Math.floor(mod.units*jog)\n var scale = mod.units*dx/(nx-1)\n var x0 = parseFloat(mod.ox.value)\n var y0 = parseFloat(mod.oy.value)\n var z0 = parseFloat(mod.oz.value)\n var xoffset = mod.units*x0\n var yoffset = mod.units*y0\n var zoffset = mod.units*z0\n var str = \"PA;PA;\" // plot absolute\n str += \"VS\"+speed+\";!VZ\"+speed+\";\"\n str += \"!PZ\"+0+\",\"+ijog+\";\" // set jog\n str += \"!MC1;\\n\" // turn motor on\n //\n // follow segments\n //\n for (var seg = 0; seg < mod.path.length; ++seg) {\n //\n // move up to starting point\n //\n x = xoffset+scale*mod.path[seg][0][0]\n y = yoffset+scale*mod.path[seg][0][1]\n str += \"PU\"+x.toFixed(0)+\",\"+y.toFixed(0)+\";\\n\"\n //\n // move down\n //\n z = zoffset+scale*mod.path[seg][0][2]\n str += \"Z\"+x.toFixed(0)+\",\"+y.toFixed(0)+\",\"+z.toFixed(0)+\";\\n\"\n for (var pt = 1; pt < mod.path[seg].length; ++pt) {\n //\n // move to next point\n //\n x = xoffset+scale*mod.path[seg][pt][0]\n y = yoffset+scale*mod.path[seg][pt][1]\n z = zoffset+scale*mod.path[seg][pt][2]\n str += \"Z\"+x.toFixed(0)+\",\"+y.toFixed(0)+\",\"+z.toFixed(0)+\";\\n\"\n }\n //\n // move up\n //\n str += \"PU\"+x.toFixed(0)+\",\"+y.toFixed(0)+\";\\n\"\n }\n //\n // turn off motor and move back\n //\n var xhome = mod.units*parseFloat(mod.hx.value)\n var yhome = mod.units*parseFloat(mod.hy.value)\n var zhome = mod.units*parseFloat(mod.hz.value)\n str += \"PA;PA;!PZ0,\"+zhome+\";PU\"+xhome+\",\"+yhome+\";!MC0;\"\n //\n // output string\n //\n var obj = {}\n obj.type = 'file'\n obj.name = mod.name+'.rml'\n obj.contents = str\n outputs.file.event(obj)\n }\n//\n// return values\n//\nreturn ({\n name:name,\n init:init,\n inputs:inputs,\n outputs:outputs,\n interface:interface\n })\n}())\n","top":"981.3223429160827","left":"677.9279893313669","filename":"modules/path/machines/Roland/milling/SRM-20","inputs":{},"outputs":{}},"0.1219393240810458":{"definition":"//\n// mill raster 3D\n//\n// Neil Gershenfeld 10/22/21\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 = 'mill raster 3D'\n//\n// initialization\n//\nvar init = function() {\n mod.dia_in.value = '0.125'\n mod.dia_mm.value = '3.175'\n mod.stepover.value = '0.5'\n mod.error.value = '0.001'\n }\n//\n// inputs\n//\nvar inputs = {\n map:{type:'',label:'height map',\n event:function(evt){\n mod.map = evt.detail.map\n mod.xmin = evt.detail.xmin\n mod.xmax = evt.detail.xmax\n mod.ymin = evt.detail.ymin\n mod.ymax = evt.detail.ymax\n mod.zmin = evt.detail.zmin\n mod.zmax = evt.detail.zmax\n mod.width = evt.detail.width\n mod.height = evt.detail.height\n mod.depth = Math.floor((mod.zmax-mod.zmin)*mod.width/(mod.xmax-mod.xmin))\n mod.mmunits = evt.detail.mmunits\n mod.dpi = mod.width/(mod.mmunits*(mod.xmax-mod.xmin)/25.4)\n var ctx = mod.img.getContext(\"2d\")\n ctx.canvas.width = mod.width\n ctx.canvas.height = mod.height\n }}}\n//\n// outputs\n//\nvar outputs = {\n toolpath:{type:'',\n event:function(){\n obj = {}\n obj.path = mod.path\n obj.name = \"mill raster 3D\"\n obj.dpi = mod.dpi\n obj.width = mod.width\n obj.height = mod.height\n obj.depth = mod.depth\n mods.output(mod,'toolpath',obj)\n }}}\n//\n// interface\n//\nvar interface = function(div){\n mod.div = div\n //\n // tool diameter\n //\n div.appendChild(document.createTextNode('tool diameter'))\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode('mm: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('input',function(){\n mod.dia_in.value = parseFloat(mod.dia_mm.value)/25.4\n })\n div.appendChild(input)\n mod.dia_mm = input\n div.appendChild(document.createTextNode(' in: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('input',function(){\n mod.dia_mm.value = parseFloat(mod.dia_in.value)*25.4\n })\n div.appendChild(input)\n mod.dia_in = input\n div.appendChild(document.createElement('br'))\n //\n // stepover\n //\n div.appendChild(document.createTextNode('stepover (0-1): '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n div.appendChild(input)\n mod.stepover = input\n div.appendChild(document.createElement('br'))\n //\n // tool shape\n //\n div.appendChild(document.createTextNode('tool shape: '))\n var input = document.createElement('input')\n input.type = 'radio'\n input.name = mod.div.id+'shape'\n input.id = mod.div.id+'flatend'\n input.checked = true\n div.appendChild(input)\n mod.flatend= input\n div.appendChild(document.createTextNode('flat end'))\n div.appendChild(document.createElement('br'))\n //\n // direction \n //\n div.appendChild(document.createTextNode('direction: '))\n var input = document.createElement('input')\n input.type = 'checkbox'\n input.id = mod.div.id+'xz'\n input.checked = true\n div.appendChild(input)\n mod.dirxz = input\n div.appendChild(document.createTextNode('xz'))\n var input = document.createElement('input')\n input.type = 'checkbox'\n input.id = mod.div.id+'yz'\n input.checked = true\n div.appendChild(input)\n mod.diryz = input\n div.appendChild(document.createTextNode('yz'))\n div.appendChild(document.createElement('br'))\n //\n // fit error \n //\n div.appendChild(document.createTextNode('vector fit: '))\n //div.appendChild(document.createElement('br'))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n div.appendChild(input)\n mod.error = input\n div.appendChild(document.createElement('br'))\n //\n // calculate\n //\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('calculate')\n mod.label = text\n span.appendChild(text)\n mod.labelspan = span\n btn.appendChild(span)\n btn.addEventListener('click',function(){\n mod.label.nodeValue = 'calculating'\n mod.labelspan.style.fontWeight = 'bold'\n calculate_path()\n })\n div.appendChild(btn)\n div.appendChild(document.createTextNode(' '))\n //\n // view\n //\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 var win = window.open('')\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 })\n win.document.body.appendChild(btn)\n win.document.body.appendChild(document.createElement('br'))\n var svg = document.getElementById(mod.div.id+'svg')\n var clone = svg.cloneNode(true)\n clone.setAttribute('width',mod.img.width)\n clone.setAttribute('height',mod.img.height)\n win.document.body.appendChild(clone)\n })\n div.appendChild(btn)\n div.appendChild(document.createElement('br'))\n //\n // on-screen SVG\n //\n var svgNS = \"http://www.w3.org/2000/svg\"\n var svg = document.createElementNS(svgNS,\"svg\")\n svg.setAttribute('id',mod.div.id+'svg')\n svg.setAttributeNS(\"http://www.w3.org/2000/xmlns/\",\n \"xmlns:xlink\",\"http://www.w3.org/1999/xlink\")\n svg.setAttribute('width',mods.ui.canvas)\n svg.setAttribute('height',mods.ui.canvas)\n svg.style.backgroundColor = 'rgb(255,255,255)'\n var g = document.createElementNS(svgNS,'g')\n g.setAttribute('id',mod.div.id+'g')\n svg.appendChild(g)\n div.appendChild(svg)\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//\n// local functions\n//\n// calculate path\n//\nfunction calculate_path() {\n var blob = new Blob(['('+calculate_path_worker.toString()+'())'])\n var url = window.URL.createObjectURL(blob)\n var webworker = new Worker(url)\n webworker.addEventListener('message',function(evt) {\n if (evt.data.type == \"progress\") {\n mod.label.nodeValue = evt.data.value\n return\n }\n //\n // webworker handler\n //\n mod.path = evt.data.path\n mod.label.nodeValue = 'calculate'\n mod.labelspan.style.fontWeight = 'normal'\n //\n // clear SVG\n //\n var svg = document.getElementById(mod.div.id+'svg')\n svg.setAttribute('viewBox',\"0 0 \"+(mod.width-1)+\" \"+(mod.height-1))\n var g = document.getElementById(mod.div.id+'g')\n svg.removeChild(g)\n var g = document.createElementNS('http://www.w3.org/2000/svg','g')\n g.setAttribute('id',mod.div.id+'g')\n svg.appendChild(g)\n //\n // plot path\n //\n for (var i = 1; i < mod.path[0].length; ++i) {\n var ixp = mod.path[0][i-1][0]\n var iyp = mod.height-1-mod.path[0][i-1][1]\n var izp = 0.1*mod.path[0][i-1][2]\n var ix = mod.path[0][i][0]\n var iy = mod.height-1-mod.path[0][i][1]\n var iz = 0.1*mod.path[0][i][2]\n var line = document.createElementNS(\n 'http://www.w3.org/2000/svg','line')\n line.setAttribute('stroke','black')\n line.setAttribute('stroke-width',1)\n line.setAttribute('stroke-linecap','round')\n line.setAttribute('x1',ixp)\n line.setAttribute('y1',iyp-izp)\n line.setAttribute('x2',ix)\n line.setAttribute('y2',iy-iz)\n g.appendChild(line)\n }\n //\n // output path\n //\n outputs.toolpath.event()\n })\n //\n // call webworker\n //\n webworker.postMessage({\n height:mod.height,width:mod.width,\n error:mod.error.value,\n xmin:mod.xmin,xmax:mod.xmax,\n ymin:mod.ymin,ymax:mod.ymax,\n zmin:mod.zmin,zmax:mod.zmax,\n diameter:mod.dia_mm.value,\n stepover:mod.stepover.value,\n mmunits: mod.mmunits,\n xz:mod.dirxz.checked,\n yz:mod.diryz.checked,\n map:mod.map})\n }\n//\n// calculate path worker\n//\nfunction calculate_path_worker() {\n self.addEventListener('message',function(evt) {\n var h = evt.data.height\n var w = evt.data.width\n var error = evt.data.error\n var xmin = evt.data.xmin\n var xmax = evt.data.xmax\n var ymin = evt.data.ymin\n var ymax = evt.data.ymax\n var zmin = evt.data.zmin\n var zmax = evt.data.zmax\n var map = evt.data.map\n var diameter = evt.data.diameter\n var stepover = evt.data.stepover\n var mmunits = evt.data.mmunits\n var step = Math.floor(stepover*diameter*w/(mmunits*(xmax-xmin)))\n var path = []\n //\n // construct tool offset\n //\n var toolsize = Math.floor(diameter*w/(mmunits*(xmax-xmin)))\n var tooloffset = new Float32Array(toolsize*toolsize)\n var toolmiddle = Math.floor(toolsize/2)\n for (var x = 0; x < toolsize; ++x)\n for (var y = 0; y < toolsize; ++y) {\n var r = Math.sqrt((x-toolmiddle)*(x-toolmiddle)+(y-toolmiddle)*(y-toolmiddle))\n if (r <= toolmiddle)\n tooloffset[y*toolsize+x] = 0\n else\n tooloffset[y*toolsize+x] = Number.MAX_VALUE\n }\n //\n // xz\n //\n if (evt.data.xz) {\n path.push([])\n var xstart = 0\n var ystart = h-1\n var zstart = Math.floor((map[ystart*w+xstart]-zmax)*w/(xmax-xmin))\n path[path.length-1].push([xstart,h-1-ystart,zstart])\n var xcur = 1\n var ycur = h-1\n var zcur = Math.floor((map[ycur*w+xcur]-zmax)*w/(xmax-xmin))\n var dx = 1\n var dy = 0\n while (1) {\n //\n // move to next point\n //\n xnext = xcur+dx\n ynext = ycur+dy\n if (ynext <= 0)\n //\n // done\n //\n break;\n //\n // find offset at next point\n //\n var znext = -Number.MAX_VALUE\n for (var xoffset = 0; xoffset < toolsize; ++xoffset)\n for (var yoffset = 0; yoffset < toolsize; ++yoffset) {\n var x = xnext+(xoffset-toolmiddle)\n var y = ynext+(yoffset-toolmiddle)\n var offset = tooloffset[yoffset*toolsize+xoffset]\n var z = Math.floor((map[y*w+x]-zmax)*w/(xmax-xmin))-offset\n if (z > znext)\n znext = z\n }\n //\n // vectorize\n //\n dxcur = xcur-xstart\n dycur = ycur-ystart\n dzcur = zcur-zstart\n dcur = Math.sqrt(dxcur*dxcur+dycur*dycur+dzcur*dzcur)\n nxcur = dxcur/dcur\n nycur = dycur/dcur\n nzcur = dzcur/dcur\n dxnext = xnext-xcur\n dynext = ynext-ycur\n dznext = znext-zcur\n dnext = Math.sqrt(dxnext*dxnext+dynext*dynext+dznext*dznext)\n nxnext = dxnext/dnext\n nynext = dynext/dnext\n nznext = dznext/dnext\n dot = nxcur*nxnext+nycur*nynext+nzcur*nznext\n if (dot <= (1-error)) {\n path[path.length-1].push([xcur,h-1-ycur,zcur])\n xstart = xcur\n ystart = ycur\n zstart = zcur\n }\n xcur = xnext\n ycur = ynext\n zcur = znext\n if (xcur == (w-1)) {\n if (dx == 1) {\n dx = 0\n dy = -step\n }\n else {\n dx = -1\n dy = 0\n }\n }\n else if (xcur == 0) {\n if (dx == -1) {\n dx = 0\n dy = -step\n }\n else {\n dx = 1\n dy = 0\n }\n }\n //\n // update progress\n //\n self.postMessage({type:'progress',value:ycur})\n }\n }\n //\n // yz\n //\n if (evt.data.yz) {\n path.push([])\n var xstart = w-1\n var ystart = 0\n var zstart = Math.floor((map[ystart*w+xstart]-zmax)*w/(xmax-xmin))\n path[path.length-1].push([xstart,h-1-ystart,zstart])\n var xcur = w-1\n var ycur = 1\n var zcur = Math.floor((map[ycur*w+xcur]-zmax)*w/(xmax-xmin))\n var dx = 0\n var dy = 1\n while (1) {\n //\n // move to next point\n //\n xnext = xcur+dx\n ynext = ycur+dy\n if (xnext <= 0)\n //\n // done\n //\n break;\n //\n // find offset at next point\n //\n var znext = -Number.MAX_VALUE\n for (var xoffset = 0; xoffset < toolsize; ++xoffset)\n for (var yoffset = 0; yoffset < toolsize; ++yoffset) {\n var x = xnext+(xoffset-toolmiddle)\n var y = ynext+(yoffset-toolmiddle)\n var offset = tooloffset[yoffset*toolsize+xoffset]\n var z = Math.floor((map[y*w+x]-zmax)*w/(xmax-xmin))-offset\n if (z > znext)\n znext = z\n }\n //\n // vectorize\n //\n dxcur = xcur-xstart\n dycur = ycur-ystart\n dzcur = zcur-zstart\n dcur = Math.sqrt(dxcur*dxcur+dycur*dycur+dzcur*dzcur)\n nxcur = dxcur/dcur\n nycur = dycur/dcur\n nzcur = dzcur/dcur\n dxnext = xnext-xcur\n dynext = ynext-ycur\n dznext = znext-zcur\n dnext = Math.sqrt(dxnext*dxnext+dynext*dynext+dznext*dznext)\n nxnext = dxnext/dnext\n nynext = dynext/dnext\n nznext = dznext/dnext\n dot = nxcur*nxnext+nycur*nynext+nzcur*nznext\n if (dot <= (1-error)) {\n path[path.length-1].push([xcur,h-1-ycur,zcur])\n xstart = xcur\n ystart = ycur\n zstart = zcur\n }\n xcur = xnext\n ycur = ynext\n zcur = znext\n if (ycur == (w-1)) {\n if (dy == 1) {\n dy = 0\n dx = -step\n }\n else {\n dy = -1\n dx = 0\n }\n }\n else if (ycur == 0) {\n if (dy == -1) {\n dy = 0\n dx = -step\n }\n else {\n dy = 1\n dx = 0\n }\n }\n //\n // update progress\n //\n self.postMessage({type:'progress',value:xcur})\n }\n }\n //\n // return\n //\n self.postMessage({type:'path',path:path})\n self.close()\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","top":"793.2645072647551","left":"258.7730903783895","filename":"modules/processes/mill/raster/3D","inputs":{},"outputs":{}}},"links":["{\"source\":\"{\\\"id\\\":\\\"0.0622871075904039\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"mesh\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.908940842104825\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"mesh\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.908940842104825\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"mesh\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.373975449262817\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"mesh\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.3062798763523076\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"file\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.5958662931535647\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"file\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.373975449262817\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"map\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.1219393240810458\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"map\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.1219393240810458\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"toolpath\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.21976500984768532\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"path\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.1219393240810458\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"toolpath\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.3062798763523076\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"path\\\"}\"}"]}
\ No newline at end of file
{"modules":{"0.0622871075904039":{"definition":"//\n// read stl\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 = 'read STL'\n//\n// initialization\n//\nvar init = function() {\n }\n//\n// inputs\n//\nvar inputs = {\n }\n//\n// outputs\n//\nvar outputs = {\n mesh:{type:'STL',\n event:function(buffer){\n mods.output(mod,'mesh',buffer)}}\n }\n//\n// interface\n//\nvar interface = function(div){\n mod.div = div\n //\n // file input control\n //\n var file = document.createElement('input')\n file.setAttribute('type','file')\n file.setAttribute('id',div.id+'file_input')\n file.style.position = 'absolute'\n file.style.left = 0\n file.style.top = 0\n file.style.width = 0\n file.style.height = 0\n file.style.opacity = 0\n file.addEventListener('change',function() {\n stl_read_handler()\n })\n div.appendChild(file)\n mod.file = file\n //\n // 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 // file select 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('select stl file'))\n btn.addEventListener('click',function(){\n var file = document.getElementById(div.id+'file_input')\n file.value = null\n file.click()\n })\n div.appendChild(btn)\n div.appendChild(document.createElement('br'))\n //\n // info\n //\n var info = document.createElement('div')\n info.setAttribute('id',div.id+'info')\n var text = document.createTextNode('name: ')\n info.appendChild(text)\n mod.namen = text\n info.appendChild(document.createElement('br'))\n var text = document.createTextNode('size: ')\n info.appendChild(text)\n mod.sizen = text\n info.appendChild(document.createElement('br'))\n var text = document.createTextNode('triangles: ')\n info.appendChild(text)\n mod.trianglesn = text\n info.appendChild(document.createElement('br'))\n var text = document.createTextNode('dx: ')\n info.appendChild(text)\n mod.dxn = text\n info.appendChild(document.createElement('br'))\n var text = document.createTextNode('dy: ')\n info.appendChild(text)\n mod.dyn = text\n info.appendChild(document.createElement('br'))\n var text = document.createTextNode('dz: ')\n info.appendChild(text)\n mod.dzn = text\n div.appendChild(info)\n }\n//\n// local functions\n//\n// read handler\n//\nfunction stl_read_handler(event) {\n var file_reader = new FileReader()\n file_reader.onload = stl_load_handler\n input_file = mod.file.files[0]\n file_name = input_file.name\n mod.namen.nodeValue = 'name: '+file_name\n file_reader.readAsArrayBuffer(input_file)\n }\n//\n// load handler\n//\nfunction stl_load_handler(event) {\n //\n // check for binary STL\n //\n var endian = true\n var view = new DataView(event.target.result)\n var triangles = view.getUint32(80,endian)\n var size = 80+4+triangles*(4*12+2)\n if (size != view.byteLength) {\n mod.sizen.nodeValue = 'error: not binary STL'\n mod.trianglesn.nodeValue = ''\n mod.dxn.nodeValue = ''\n mod.dyn.nodeValue = ''\n mod.dzn.nodeValue = ''\n return\n }\n mod.sizen.nodeValue = 'size: '+size\n mod.trianglesn.nodeValue = 'triangles: '+triangles\n //\n // find limits and draw\n //\n var blob = new Blob(['('+draw_limits_worker.toString()+'())'])\n var url = window.URL.createObjectURL(blob)\n var webworker = new Worker(url)\n webworker.addEventListener('message',function(evt) {\n //\n // worker response\n //\n window.URL.revokeObjectURL(url)\n //\n // size\n //\n mod.dxn.nodeValue = 'dx: '+evt.data.dx.toFixed(3)\n mod.dyn.nodeValue = 'dy: '+evt.data.dy.toFixed(3)\n mod.dzn.nodeValue = 'dz: '+evt.data.dz.toFixed(3)\n //\n // image\n //\n var image = evt.data.image\n var height = mod.canvas.height\n var width = mod.canvas.width\n var buffer = new Uint8ClampedArray(evt.data.image)\n var imgdata = new ImageData(buffer,width,height)\n var ctx = mod.canvas.getContext(\"2d\")\n ctx.putImageData(imgdata,0,0)\n //\n // output\n //\n outputs.mesh.event(evt.data.mesh)\n })\n var ctx = mod.canvas.getContext(\"2d\")\n ctx.clearRect(0,0,mod.canvas.width,mod.canvas.height)\n var img = ctx.getImageData(0,0,mod.canvas.width,mod.canvas.height)\n //\n // call worker\n //\n webworker.postMessage({\n height:mod.canvas.height,width:mod.canvas.width,\n image:img.data.buffer,mesh:event.target.result},\n [img.data.buffer,event.target.result])\n }\nfunction draw_limits_worker() {\n self.addEventListener('message',function(evt) {\n //\n // function to draw line\n //\n function line(x0,y0,x1,y1) {\n var ix0 = Math.floor(xo+xw*(x0-xmin)/dx)\n var iy0 = Math.floor(yo+yh*(ymax-y0)/dy)\n var ix1 = Math.floor(xo+xw*(x1-xmin)/dx)\n var iy1 = Math.floor(yo+yh*(ymax-y1)/dy)\n var row,col\n var idx = ix1-ix0\n var idy = iy1-iy0\n if (Math.abs(idy) > Math.abs(idx)) {\n (idy > 0) ?\n (row0=iy0,col0=ix0,row1=iy1,col1=ix1):\n (row0=iy1,col0=ix1,row1=iy0,col1=ix0)\n for (row = row0; row <= row1; ++row) {\n col = Math.floor(col0+(col1-col0)*(row-row0)/(row1-row0))\n image[row*width*4+col*4+0] = 0\n image[row*width*4+col*4+1] = 0\n image[row*width*4+col*4+2] = 0\n image[row*width*4+col*4+3] = 255\n }\n }\n else if ((Math.abs(idx) >= Math.abs(idy)) && (idx != 0)) {\n (idx > 0) ?\n (row0=iy0,col0=ix0,row1=iy1,col1=ix1):\n (row0=iy1,col0=ix1,row1=iy0,col1=ix0)\n for (col = col0; col <= col1; ++col) {\n row = Math.floor(row0+(row1-row0)*(col-col0)/(col1-col0))\n image[row*width*4+col*4+0] = 0\n image[row*width*4+col*4+1] = 0\n image[row*width*4+col*4+2] = 0\n image[row*width*4+col*4+3] = 255\n }\n }\n else {\n row = iy0\n col = ix0\n image[row*width*4+col*4+0] = 0\n image[row*width*4+col*4+1] = 0\n image[row*width*4+col*4+2] = 0\n image[row*width*4+col*4+3] = 255\n }\n }\n //\n // get variables\n //\n var height = evt.data.height\n var width = evt.data.width\n var endian = true\n var image = new Uint8ClampedArray(evt.data.image)\n var view = new DataView(evt.data.mesh)\n var triangles = view.getUint32(80,endian)\n //\n // find limits\n //\n var offset = 80+4\n var x0,x1,x2,y0,y1,y2,z0,z1,z2\n var xmin = Number.MAX_VALUE\n var xmax = -Number.MAX_VALUE\n var ymin = Number.MAX_VALUE\n var ymax = -Number.MAX_VALUE\n var zmin = Number.MAX_VALUE\n var zmax = -Number.MAX_VALUE\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n if (x0 > xmax) xmax = x0\n if (x0 < xmin) xmin = x0\n y0 = view.getFloat32(offset,endian)\n offset += 4\n if (y0 > ymax) ymax = y0\n if (y0 < ymin) ymin = y0\n z0 = view.getFloat32(offset,endian)\n offset += 4\n if (z0 > zmax) zmax = z0\n if (z0 < zmin) zmin = z0\n x1 = view.getFloat32(offset,endian)\n offset += 4\n if (x1 > xmax) xmax = x1\n if (x1 < xmin) xmin = x1\n y1 = view.getFloat32(offset,endian)\n offset += 4\n if (y1 > ymax) ymax = y1\n if (y1 < ymin) ymin = y1\n z1 = view.getFloat32(offset,endian)\n offset += 4\n if (z1 > zmax) zmax = z1\n if (z1 < zmin) zmin = z1\n x2 = view.getFloat32(offset,endian)\n offset += 4\n if (x2 > xmax) xmax = x2\n if (x2 < xmin) xmin = x2\n y2 = view.getFloat32(offset,endian)\n offset += 4\n if (y2 > ymax) ymax = y2\n if (y2 < ymin) ymin = y2\n z2 = view.getFloat32(offset,endian)\n offset += 4\n if (z2 > zmax) zmax = z2\n if (z2 < zmin) zmin = z2\n offset += 2\n }\n var dx = xmax-xmin\n var dy = ymax-ymin\n var dz = zmax-zmin\n //\n // draw mesh\n //\n if (dx > dy) {\n var xo = 0\n var yo = height*.5*(1-dy/dx)\n var xw = width-1\n var yh = (width-1)*dy/dx\n }\n else {\n var xo = width*.5*(1-dx/dy)\n var yo = 0\n var xw = (height-1)*dx/dy\n var yh = height-1\n }\n offset = 80+4\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n y0 = view.getFloat32(offset,endian)\n offset += 4\n z0 = view.getFloat32(offset,endian)\n offset += 4\n x1 = view.getFloat32(offset,endian)\n offset += 4\n y1 = view.getFloat32(offset,endian)\n offset += 4\n z1 = view.getFloat32(offset,endian)\n offset += 4\n x2 = view.getFloat32(offset,endian)\n offset += 4\n y2 = view.getFloat32(offset,endian)\n offset += 4\n z2 = view.getFloat32(offset,endian)\n offset += 4\n offset += 2\n line(x0,y0,x1,y1)\n line(x1,y1,x2,y2)\n line(x2,y2,x0,y0)\n }\n //\n // return results and close\n //\n self.postMessage({\n dx:dx,dy:dy,dz:dz,\n image:evt.data.image,mesh:evt.data.mesh},[evt.data.image,evt.data.mesh])\n self.close()\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":"121.4689005070139","left":"231.1238074852728","filename":"undefined","inputs":{},"outputs":{}},"0.908940842104825":{"definition":"//\n// mesh rotate\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 = 'mesh rotate'\n//\n// initialization\n//\nvar init = function() {\n mod.rx.value = '0'\n mod.ry.value = '0'\n mod.rz.value = '0'\n }\n//\n// inputs\n//\nvar inputs = {\n mesh:{type:'STL',\n event:function(evt){\n mod.mesh = evt.detail\n rotate_mesh()}}}\n//\n// outputs\n//\nvar outputs = {\n mesh:{type:'STL',\n event:function(buffer){\n mods.output(mod,'mesh',buffer)}}}\n//\n// interface\n//\nvar interface = function(div){\n mod.div = div\n //\n // 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 // rotation\n //\n div.appendChild(document.createTextNode('rotation (degrees):'))\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode(' x: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('change',function(){\n rotate_mesh()\n })\n div.appendChild(input)\n mod.rx = input\n div.appendChild(document.createTextNode(' y: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('change',function(){\n rotate_mesh()\n })\n div.appendChild(input)\n mod.ry = input\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode(' z: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('change',function(){\n rotate_mesh()\n })\n div.appendChild(input)\n mod.rz = input\n div.appendChild(document.createTextNode(' (enter)'))\n div.appendChild(document.createElement('br'))\n //\n // info\n //\n var text = document.createTextNode('dx:')\n div.appendChild(text)\n mod.dxn = text\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('dy:')\n div.appendChild(text)\n mod.dyn = text\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('dz:')\n div.appendChild(text)\n mod.dzn = text\n div.appendChild(document.createElement('br'))\n }\n//\n// local functions\n//\n// rotate mesh\n//\nfunction rotate_mesh() {\n //\n // check for binary STL\n //\n var endian = true\n var view = new DataView(mod.mesh)\n var triangles = view.getUint32(80,endian)\n var size = 80+4+triangles*(4*12+2)\n //\n // find limits, rotate, and draw\n //\n var blob = new Blob(['('+rotate_mesh_worker.toString()+'())'])\n var url = window.URL.createObjectURL(blob)\n var webworker = new Worker(url)\n webworker.addEventListener('message',function(evt) {\n //\n // worker response\n //\n window.URL.revokeObjectURL(url)\n //\n // size\n //\n mod.dxn.nodeValue = 'dx: '+evt.data.dx.toFixed(3)\n mod.dyn.nodeValue = 'dy: '+evt.data.dy.toFixed(3)\n mod.dzn.nodeValue = 'dz: '+evt.data.dz.toFixed(3)\n //\n // image\n //\n var image = evt.data.image\n var height = mod.canvas.height\n var width = mod.canvas.width\n var buffer = new Uint8ClampedArray(evt.data.image)\n var imgdata = new ImageData(buffer,width,height)\n var ctx = mod.canvas.getContext(\"2d\")\n ctx.putImageData(imgdata,0,0)\n //\n // mesh\n //\n mod.mesh = evt.data.mesh\n //\n // output\n //\n outputs.mesh.event(evt.data.rotate)\n })\n //\n // call worker\n //\n var ctx = mod.canvas.getContext(\"2d\")\n ctx.clearRect(0,0,mod.canvas.width,mod.canvas.height)\n var img = ctx.getImageData(0,0,mod.canvas.width,mod.canvas.height)\n var rx = parseFloat(mod.rx.value)*Math.PI/180\n var ry = parseFloat(mod.ry.value)*Math.PI/180\n var rz = parseFloat(mod.rz.value)*Math.PI/180\n webworker.postMessage({\n height:mod.canvas.height,width:mod.canvas.width,\n rx:rx,ry:ry,rz:rz,\n image:img.data.buffer,mesh:mod.mesh},\n [img.data.buffer,mod.mesh])\n }\nfunction rotate_mesh_worker() {\n self.addEventListener('message',function(evt) {\n //\n // function to draw line\n //\n function line(x0,y0,x1,y1) {\n var ix0 = Math.floor(xo+xw*(x0-xmin)/dx)\n var iy0 = Math.floor(yo+yh*(ymax-y0)/dy)\n var ix1 = Math.floor(xo+xw*(x1-xmin)/dx)\n var iy1 = Math.floor(yo+yh*(ymax-y1)/dy)\n var row,col\n var idx = ix1-ix0\n var idy = iy1-iy0\n if (Math.abs(idy) > Math.abs(idx)) {\n (idy > 0) ?\n (row0=iy0,col0=ix0,row1=iy1,col1=ix1):\n (row0=iy1,col0=ix1,row1=iy0,col1=ix0)\n for (row = row0; row <= row1; ++row) {\n col = Math.floor(col0+(col1-col0)*(row-row0)/(row1-row0))\n image[row*width*4+col*4+0] = 0\n image[row*width*4+col*4+1] = 0\n image[row*width*4+col*4+2] = 0\n image[row*width*4+col*4+3] = 255\n }\n }\n else if ((Math.abs(idx) >= Math.abs(idy)) && (idx != 0)) {\n (idx > 0) ?\n (row0=iy0,col0=ix0,row1=iy1,col1=ix1):\n (row0=iy1,col0=ix1,row1=iy0,col1=ix0)\n for (col = col0; col <= col1; ++col) {\n row = Math.floor(row0+(row1-row0)*(col-col0)/(col1-col0))\n image[row*width*4+col*4+0] = 0\n image[row*width*4+col*4+1] = 0\n image[row*width*4+col*4+2] = 0\n image[row*width*4+col*4+3] = 255\n }\n }\n else {\n row = iy0\n col = ix0\n image[row*width*4+col*4+0] = 0\n image[row*width*4+col*4+1] = 0\n image[row*width*4+col*4+2] = 0\n image[row*width*4+col*4+3] = 255\n }\n }\n //\n // function to rotate point\n //\n function rotate(x,y,z) {\n var x1 = x\n var y1 = Math.cos(rx)*y-Math.sin(rx)*z\n var z1 = Math.sin(rx)*y+Math.cos(rx)*z\n var x2 = Math.cos(ry)*x1-Math.sin(ry)*z1\n var y2 = y1\n var z2 = Math.sin(ry)*x1+Math.cos(ry)*z1\n var x3 = Math.cos(rz)*x2-Math.sin(rz)*y2\n var y3 = Math.sin(rz)*x2+Math.cos(rz)*y2\n var z3 = z2\n //return([x3,y3,z3])\n return({x:x3,y:y3,z:z3})\n }\n //\n // get variables\n //\n var height = evt.data.height\n var width = evt.data.width\n var rx = evt.data.rx\n var ry = evt.data.ry\n var rz = evt.data.rz\n var endian = true\n var image = new Uint8ClampedArray(evt.data.image)\n var view = new DataView(evt.data.mesh)\n var triangles = view.getUint32(80,endian)\n //\n // find limits\n //\n var offset = 80+4\n var x0,x1,x2,y0,y1,y2,z0,z1,z2\n var xmin = Number.MAX_VALUE\n var xmax = -Number.MAX_VALUE\n var ymin = Number.MAX_VALUE\n var ymax = -Number.MAX_VALUE\n var zmin = Number.MAX_VALUE\n var zmax = -Number.MAX_VALUE\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n y0 = view.getFloat32(offset,endian)\n offset += 4\n z0 = view.getFloat32(offset,endian)\n offset += 4\n x1 = view.getFloat32(offset,endian)\n offset += 4\n y1 = view.getFloat32(offset,endian)\n offset += 4\n z1 = view.getFloat32(offset,endian)\n offset += 4\n x2 = view.getFloat32(offset,endian)\n offset += 4\n y2 = view.getFloat32(offset,endian)\n offset += 4\n z2 = view.getFloat32(offset,endian)\n offset += 4\n offset += 2\n var p0 = rotate(x0,y0,z0)\n if (p0.x > xmax) xmax = p0.x\n if (p0.x < xmin) xmin = p0.x\n if (p0.y > ymax) ymax = p0.y\n if (p0.y < ymin) ymin = p0.y\n if (p0.z > zmax) zmax = p0.z\n if (p0.z < zmin) zmin = p0.z\n var p1 = rotate(x1,y1,z1)\n if (p1.x > xmax) xmax = p1.x\n if (p1.x < xmin) xmin = p1.x\n if (p1.y > ymax) ymax = p1.y\n if (p1.y < ymin) ymin = p1.y\n if (p1.z > zmax) zmax = p1.z\n if (p1.z < zmin) zmin = p1.z\n var p2 = rotate(x2,y2,z2)\n if (p2.x > xmax) xmax = p2.x\n if (p2.x < xmin) xmin = p2.x\n if (p2.y > ymax) ymax = p2.y\n if (p2.y < ymin) ymin = p2.y\n if (p2.z > zmax) zmax = p2.z\n if (p2.z < zmin) zmin = p2.z\n }\n var dx = xmax-xmin\n var dy = ymax-ymin\n var dz = zmax-zmin\n //\n // copy mesh\n //\n var newbuf = evt.data.mesh.slice(0)\n var newview = new DataView(newbuf)\n //\n // copy and draw mesh\n //\n if (dx > dy) {\n var xo = 0\n var yo = height*.5*(1-dy/dx)\n var xw = (width-1)\n var yh = (width-1)*dy/dx\n }\n else {\n var xo = width*.5*(1-dx/dy)\n var yo = 0\n var xw = (height-1)*dx/dy\n var yh = (height-1)\n }\n offset = 80+4\n var newoffset = 80+4\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n y0 = view.getFloat32(offset,endian)\n offset += 4\n z0 = view.getFloat32(offset,endian)\n offset += 4\n x1 = view.getFloat32(offset,endian)\n offset += 4\n y1 = view.getFloat32(offset,endian)\n offset += 4\n z1 = view.getFloat32(offset,endian)\n offset += 4\n x2 = view.getFloat32(offset,endian)\n offset += 4\n y2 = view.getFloat32(offset,endian)\n offset += 4\n z2 = view.getFloat32(offset,endian)\n offset += 4\n offset += 2\n var p0 = rotate(x0,y0,z0)\n var p1 = rotate(x1,y1,z1)\n var p2 = rotate(x2,y2,z2)\n line(p0.x,p0.y,p1.x,p1.y)\n line(p1.x,p1.y,p2.x,p2.y)\n line(p2.x,p2.y,p0.x,p0.y)\n newoffset += 3*4\n newview.setFloat32(newoffset,p0.x,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p0.y,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p0.z,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p1.x,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p1.y,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p1.z,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p2.x,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p2.y,endian)\n newoffset += 4\n newview.setFloat32(newoffset,p2.z,endian)\n newoffset += 4\n newoffset += 2\n }\n //\n // return results and close\n //\n self.postMessage({\n dx:dx,dy:dy,dz:dz,\n image:evt.data.image,mesh:evt.data.mesh,rotate:newbuf},\n [evt.data.image,evt.data.mesh,newbuf])\n self.close()\n })\n }\nfunction old_rotate_mesh() {\n //\n // function to rotate point\n //\n function rotate(x,y,z) {\n var x1 = x\n var y1 = Math.cos(rx)*y-Math.sin(rx)*z\n var z1 = Math.sin(rx)*y+Math.cos(rx)*z\n var x2 = Math.cos(ry)*x1-Math.sin(ry)*z1\n var y2 = y1\n var z2 = Math.sin(ry)*x1+Math.cos(ry)*z1\n var x3 = Math.cos(rz)*x2-Math.sin(rz)*y2\n var y3 = Math.sin(rz)*x2+Math.cos(rz)*y2\n var z3 = z2\n return([x3,y3,z3])\n }\n //\n // get vars\n //\n var view = mod.mesh\n var endian = true\n var triangles = view.getUint32(80,endian)\n mod.triangles = triangles\n var size = 80+4+triangles*(4*12+2)\n var rx = parseFloat(mod.rx.value)*Math.PI/180\n var ry = parseFloat(mod.ry.value)*Math.PI/180\n var rz = parseFloat(mod.rz.value)*Math.PI/180\n //\n // find limits\n //\n var offset = 80+4\n var x0,x1,x2,y0,y1,y2,z0,z1,z2\n var xmin = Number.MAX_VALUE\n var xmax = -Number.MAX_VALUE\n var ymin = Number.MAX_VALUE\n var ymax = -Number.MAX_VALUE\n var zmin = Number.MAX_VALUE\n var zmax = -Number.MAX_VALUE\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n y0 = view.getFloat32(offset,endian)\n offset += 4\n z0 = view.getFloat32(offset,endian)\n offset += 4\n x1 = view.getFloat32(offset,endian)\n offset += 4\n y1 = view.getFloat32(offset,endian)\n offset += 4\n z1 = view.getFloat32(offset,endian)\n offset += 4\n x2 = view.getFloat32(offset,endian)\n offset += 4\n y2 = view.getFloat32(offset,endian)\n offset += 4\n z2 = view.getFloat32(offset,endian)\n offset += 4\n offset += 2\n var p0 = rotate(x0,y0,z0)\n if (p0[0] > xmax) xmax = p0[0]\n if (p0[0] < xmin) xmin = p0[0]\n if (p0[1] > ymax) ymax = p0[1]\n if (p0[1] < ymin) ymin = p0[1]\n if (p0[2] > zmax) zmax = p0[2]\n if (p0[2] < zmin) zmin = p0[2]\n var p1 = rotate(x1,y1,z1)\n if (p1[0] > xmax) xmax = p1[0]\n if (p1[0] < xmin) xmin = p1[0]\n if (p1[1] > ymax) ymax = p1[1]\n if (p1[1] < ymin) ymin = p1[1]\n if (p1[2] > zmax) zmax = p1[2]\n if (p1[2] < zmin) zmin = p1[2]\n var p2 = rotate(x2,y2,z2)\n if (p2[0] > xmax) xmax = p2[0]\n if (p2[0] < xmin) xmin = p2[0]\n if (p2[1] > ymax) ymax = p2[1]\n if (p2[1] < ymin) ymin = p2[1]\n if (p2[2] > zmax) zmax = p2[2]\n if (p2[2] < zmin) zmin = p2[2]\n }\n mod.dx = xmax-xmin\n mod.dy = ymax-ymin\n mod.dz = zmax-zmin\n mod.dxn.nodeValue = 'dx: '+mod.dx.toFixed(3)\n mod.dyn.nodeValue = 'dy: '+mod.dy.toFixed(3)\n mod.dzn.nodeValue = 'dz: '+mod.dz.toFixed(3)\n mod.xmin = xmin\n mod.ymin = ymin\n mod.zmin = zmin\n mod.xmax = xmax\n mod.ymax = ymax\n mod.zmax = zmax\n //\n // copy mesh\n //\n var buf = mod.mesh.buffer.slice(0)\n var newview = new DataView(buf)\n //\n // draw projection and save rotation\n //\n var ctx = mod.meshcanvas.getContext('2d')\n var w = mod.meshcanvas.width\n var h = mod.meshcanvas.height\n ctx.clearRect(0,0,w,h)\n var dx = mod.dx\n var dy = mod.dy\n if (dx > dy) {\n var xo = 0\n var yo = h*.5*(1-dy/dx)\n var xw = w\n var yh = w*dy/dx\n }\n else {\n var xo = w*.5*(1-dx/dy)\n var yo = 0\n var xw = h*dx/dy\n var yh = h\n }\n ctx.beginPath()\n offset = 80+4\n var newoffset = 80+4\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n y0 = view.getFloat32(offset,endian)\n offset += 4\n z0 = view.getFloat32(offset,endian)\n offset += 4\n x1 = view.getFloat32(offset,endian)\n offset += 4\n y1 = view.getFloat32(offset,endian)\n offset += 4\n z1 = view.getFloat32(offset,endian)\n offset += 4\n x2 = view.getFloat32(offset,endian)\n offset += 4\n y2 = view.getFloat32(offset,endian)\n offset += 4\n z2 = view.getFloat32(offset,endian)\n offset += 4\n offset += 2\n var p0 = rotate(x0,y0,z0)\n var p1 = rotate(x1,y1,z1)\n var p2 = rotate(x2,y2,z2)\n x0 = xo+xw*(p0[0]-xmin)/dx\n y0 = yo+yh*(ymax-p0[1])/dy\n x1 = xo+xw*(p1[0]-xmin)/dx\n y1 = yo+yh*(ymax-p1[1])/dy\n x2 = xo+xw*(p2[0]-xmin)/dx\n y2 = yo+yh*(ymax-p2[1])/dy\n ctx.moveTo(x0,y0)\n ctx.lineTo(x1,y1)\n ctx.lineTo(x2,y2)\n ctx.lineTo(x0,y0)\n newoffset += 3*4\n newview.setFloat32(newoffset,p0[0],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p0[1],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p0[2],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p1[0],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p1[1],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p1[2],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p2[0],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p2[1],endian)\n newoffset += 4\n newview.setFloat32(newoffset,p2[2],endian)\n newoffset += 4\n newoffset += 2\n }\n ctx.stroke()\n //\n // generate output\n //\n outputs.mesh.event(buf)\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":"252.46890050701393","left":"694.1238074852727","filename":"undefined","inputs":{},"outputs":{}},"0.373975449262817":{"definition":"//\n// mesh height map\n// \n// Neil Gershenfeld 1/16/20\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 = 'mesh height map'\n//\n// initialization\n//\nvar init = function() {\n mod.mmunits.value = '25.4'\n mod.inunits.value = '1'\n mod.width.value = '1000'\n mod.border.value = '0'\n }\n//\n// inputs\n//\nvar inputs = {\n mesh:{type:'STL',\n event:function(evt){\n mod.mesh = new DataView(evt.detail)\n find_limits_map()}}}\n//\n// outputs\n//\nvar outputs = {\n map:{type:'',label:'height map',\n event:function(heightmap){\n var obj = {}\n obj.map = heightmap\n obj.xmin = mod.xmin\n obj.xmax = mod.xmax\n obj.ymin = mod.ymin\n obj.ymax = mod.ymax\n obj.zmin = mod.zmin\n obj.zmax = mod.zmax\n obj.width = mod.img.width\n obj.height = mod.img.height\n obj.mmunits = mod.mmunits.value\n mods.output(mod,'map',obj)\n }}}\n//\n// interface\n//\nvar interface = function(div){\n mod.div = div\n //\n // on-screen height map canvas\n //\n div.appendChild(document.createTextNode(' '))\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.mapcanvas = 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 // mesh units\n //\n div.appendChild(document.createTextNode('mesh units: (enter)'))\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode('mm: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('change',function(){\n mod.inunits.value = parseFloat(mod.mmunits.value)/25.4\n find_limits_map()\n })\n div.appendChild(input)\n mod.mmunits = input\n div.appendChild(document.createTextNode(' in: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('change',function(){\n mod.mmunits.value = parseFloat(mod.inunits.value)*25.4\n find_limits_map()\n })\n div.appendChild(input)\n mod.inunits = input\n //\n // mesh size\n //\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode('mesh size:'))\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('XxYxZ (units)')\n div.appendChild(text)\n mod.meshsize = text\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('XxYxZ (mm)')\n div.appendChild(text)\n mod.mmsize = text\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('XxYxZ (in)')\n div.appendChild(text)\n mod.insize = text\n //\n // height map border \n //\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode('border: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('change',function(){\n find_limits_map()\n })\n div.appendChild(input)\n mod.border = input\n div.appendChild(document.createTextNode(' (units)'))\n //\n // height map width\n //\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode('width: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('change',function(){\n find_limits_map()\n })\n div.appendChild(input)\n mod.width = input\n div.appendChild(document.createTextNode(' (pixels)'))\n //\n // view height map\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 btn.appendChild(document.createTextNode('view height map'))\n btn.addEventListener('click',function(){\n var win = window.open('')\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 })\n win.document.body.appendChild(btn)\n win.document.body.appendChild(document.createElement('br'))\n var canvas = document.createElement('canvas')\n canvas.width = mod.img.width\n canvas.height = mod.img.height\n win.document.body.appendChild(canvas)\n var ctx = canvas.getContext(\"2d\")\n ctx.drawImage(mod.img,0,0)\n })\n div.appendChild(btn)\n }\n//\n// local functions\n//\n// find limits then map \n//\nfunction find_limits_map() {\n var blob = new Blob(['('+limits_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 mod.triangles = evt.data.triangles\n mod.xmin = evt.data.xmin\n mod.xmax = evt.data.xmax\n mod.ymin = evt.data.ymin\n mod.ymax = evt.data.ymax\n mod.zmin = evt.data.zmin\n mod.zmax = evt.data.zmax\n mod.dx = mod.xmax-mod.xmin\n mod.dy = mod.ymax-mod.ymin\n mod.dz = mod.zmax-mod.zmin\n mod.meshsize.nodeValue = \n mod.dx.toFixed(3)+' x '+\n mod.dy.toFixed(3)+' x '+\n mod.dz.toFixed(3)+' (units)'\n var mm = parseFloat(mod.mmunits.value)\n mod.mmsize.nodeValue = \n (mod.dx*mm).toFixed(3)+' x '+\n (mod.dy*mm).toFixed(3)+' x '+\n (mod.dz*mm).toFixed(3)+' (mm)'\n var inches = parseFloat(mod.inunits.value)\n mod.insize.nodeValue = \n (mod.dx*inches).toFixed(3)+' x '+\n (mod.dy*inches).toFixed(3)+' x '+\n (mod.dz*inches).toFixed(3)+' (in)'\n mods.fit(mod.div)\n map_mesh()\n })\n var border = parseFloat(mod.border.value)\n webworker.postMessage({\n mesh:mod.mesh,\n border:border})\n }\nfunction limits_worker() {\n self.addEventListener('message',function(evt) {\n var view = evt.data.mesh\n var border = evt.data.border\n //\n // get vars\n //\n var endian = true\n var triangles = view.getUint32(80,endian)\n var size = 80+4+triangles*(4*12+2)\n //\n // find limits\n //\n var offset = 80+4\n var x0,x1,x2,y0,y1,y2,z0,z1,z2\n var xmin = Number.MAX_VALUE\n var xmax = -Number.MAX_VALUE\n var ymin = Number.MAX_VALUE\n var ymax = -Number.MAX_VALUE\n var zmin = Number.MAX_VALUE\n var zmax = -Number.MAX_VALUE\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n y0 = view.getFloat32(offset,endian)\n offset += 4\n z0 = view.getFloat32(offset,endian)\n offset += 4\n x1 = view.getFloat32(offset,endian)\n offset += 4\n y1 = view.getFloat32(offset,endian)\n offset += 4\n z1 = view.getFloat32(offset,endian)\n offset += 4\n x2 = view.getFloat32(offset,endian)\n offset += 4\n y2 = view.getFloat32(offset,endian)\n offset += 4\n z2 = view.getFloat32(offset,endian)\n offset += 4\n offset += 2\n if (x0 > xmax) xmax = x0\n if (x0 < xmin) xmin = x0\n if (y0 > ymax) ymax = y0\n if (y0 < ymin) ymin = y0\n if (z0 > zmax) zmax = z0\n if (z0 < zmin) zmin = z0\n if (x1 > xmax) xmax = x1\n if (x1 < xmin) xmin = x1\n if (y1 > ymax) ymax = y1\n if (y1 < ymin) ymin = y1\n if (z1 > zmax) zmax = z1\n if (z1 < zmin) zmin = z1\n if (x2 > xmax) xmax = x2\n if (x2 < xmin) xmin = x2\n if (y2 > ymax) ymax = y2\n if (y2 < ymin) ymin = y2\n if (z2 > zmax) zmax = z2\n if (z2 < zmin) zmin = z2\n }\n xmin -= border\n xmax += border\n ymin -= border\n ymax += border\n //\n // return\n //\n self.postMessage({triangles:triangles,\n xmin:xmin,xmax:xmax,ymin:ymin,ymax:ymax,\n zmin:zmin,zmax:zmax})\n self.close()\n })\n }\n//\n// map mesh\n// \nfunction map_mesh() {\n var blob = new Blob(['('+map_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.imgbuffer)\n var map = new Float32Array(evt.data.mapbuffer)\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.mapcanvas.height*.5*(1-h/w)\n var wd = mod.mapcanvas.width\n var hd = mod.mapcanvas.width*h/w\n }\n else {\n var x0 = mod.mapcanvas.width*.5*(1-w/h)\n var y0 = 0\n var wd = mod.mapcanvas.height*w/h\n var hd = mod.mapcanvas.height\n }\n var ctx = mod.mapcanvas.getContext(\"2d\")\n ctx.clearRect(0,0,mod.mapcanvas.width,mod.mapcanvas.height)\n ctx.drawImage(mod.img,x0,y0,wd,hd)\n outputs.map.event(map)\n })\n var ctx = mod.mapcanvas.getContext(\"2d\")\n ctx.clearRect(0,0,mod.mapcanvas.width,mod.mapcanvas.height)\n mod.img.width = parseInt(mod.width.value)\n mod.img.height = Math.round(mod.img.width*mod.dy/mod.dx)\n var ctx = mod.img.getContext(\"2d\")\n var img = ctx.getImageData(0,0,mod.img.width,mod.img.height)\n var map = new Float32Array(mod.img.width*mod.img.height)\n webworker.postMessage({\n height:mod.img.height,width:mod.img.width,\n imgbuffer:img.data.buffer,\n mapbuffer:map.buffer,\n mesh:mod.mesh,\n xmin:mod.xmin,xmax:mod.xmax,\n ymin:mod.ymin,ymax:mod.ymax,\n zmin:mod.zmin,zmax:mod.zmax},\n [img.data.buffer,map.buffer])\n }\nfunction map_worker() {\n self.addEventListener('message',function(evt) {\n var h = evt.data.height\n var w = evt.data.width\n var view = evt.data.mesh\n var xmin = evt.data.xmin\n var xmax = evt.data.xmax\n var ymin = evt.data.ymin\n var ymax = evt.data.ymax\n var zmin = evt.data.zmin\n var zmax = evt.data.zmax\n var buf = new Uint8ClampedArray(evt.data.imgbuffer)\n var map = new Float32Array(evt.data.mapbuffer)\n //\n // get vars from buffer\n //\n var endian = true\n var triangles = view.getUint32(80,endian)\n var size = 80+4+triangles*(4*12+2)\n //\n // initialize map and image\n //\n for (var row = 0; row < h; ++row) {\n for (var col = 0; col < w; ++col) {\n map[(h-1-row)*w+col] = zmin\n buf[(h-1-row)*w*4+col*4+0] = 0\n buf[(h-1-row)*w*4+col*4+1] = 0\n buf[(h-1-row)*w*4+col*4+2] = 0\n buf[(h-1-row)*w*4+col*4+3] = 255\n }\n }\n //\n // loop over triangles\n //\n var segs = []\n offset = 80+4\n for (var t = 0; t < triangles; ++t) {\n offset += 3*4\n x0 = view.getFloat32(offset,endian)\n offset += 4\n y0 = view.getFloat32(offset,endian)\n offset += 4\n z0 = view.getFloat32(offset,endian)\n offset += 4\n x1 = view.getFloat32(offset,endian)\n offset += 4\n y1 = view.getFloat32(offset,endian)\n offset += 4\n z1 = view.getFloat32(offset,endian)\n offset += 4\n x2 = view.getFloat32(offset,endian)\n offset += 4\n y2 = view.getFloat32(offset,endian)\n offset += 4\n z2 = view.getFloat32(offset,endian)\n offset += 4\n offset += 2\n //\n // check normal if needs to be drawn\n //\n if (((x1-x0)*(y1-y2)-(x1-x2)*(y1-y0)) >= 0)\n continue\n //\n // quantize image coordinates\n //\n x0 = Math.floor((w-1)*(x0-xmin)/(xmax-xmin))\n x1 = Math.floor((w-1)*(x1-xmin)/(xmax-xmin))\n x2 = Math.floor((w-1)*(x2-xmin)/(xmax-xmin))\n y0 = Math.floor((h-1)*(y0-ymin)/(ymax-ymin))\n y1 = Math.floor((h-1)*(y1-ymin)/(ymax-ymin))\n y2 = Math.floor((h-1)*(y2-ymin)/(ymax-ymin))\n //\n // sort projection order\n //\n if (y1 > y2) {\n var temp = x1;\n x1 = x2;\n x2 = temp\n var temp = y1;\n y1 = y2;\n y2 = temp\n var temp = z1;\n z1 = z2;\n z2 = temp\n }\n if (y0 > y1) {\n var temp = x0;\n x0 = x1;\n x1 = temp\n var temp = y0;\n y0 = y1;\n y1 = temp\n var temp = z0;\n z0 = z1;\n z1 = temp\n }\n if (y1 > y2) {\n var temp = x1;\n x1 = x2;\n x2 = temp\n var temp = y1;\n y1 = y2;\n y2 = temp\n var temp = z1;\n z1 = z2;\n z2 = temp\n }\n //\n // check orientation after sort\n //\n if (x1 < (x0+((x2-x0)*(y1-y0))/(y2-y0)))\n var dir = 1;\n else\n var dir = -1;\n //\n // set z values\n //\n if (y2 != y1) {\n for (var y = y1; y <= y2; ++y) {\n x12 = Math.floor(0.5+x1+(y-y1)*(x2-x1)/(y2-y1))\n z12 = z1+(y-y1)*(z2-z1)/(y2-y1)\n x02 = Math.floor(0.5+x0+(y-y0)*(x2-x0)/(y2-y0))\n z02 = z0+(y-y0)*(z2-z0)/(y2-y0)\n if (x12 != x02)\n var slope = (z02-z12)/(x02-x12)\n else\n var slope = 0\n var x = x12 - dir\n while (x != x02) {\n x += dir\n var z = z12+slope*(x-x12)\n if (z > map[(h-1-y)*w+x]) {\n map[(h-1-y)*w+x] = z\n var iz = Math.floor(255*(z-zmin)/(zmax-zmin))\n buf[(h-1-y)*w*4+x*4+0] = iz\n buf[(h-1-y)*w*4+x*4+1] = iz\n buf[(h-1-y)*w*4+x*4+2] = iz\n }\n }\n }\n }\n if (y1 != y0) {\n for (var y = y0; y <= y1; ++y) {\n x01 = Math.floor(0.5+x0+(y-y0)*(x1-x0)/(y1-y0))\n z01 = z0+(y-y0)*(z1-z0)/(y1-y0)\n x02 = Math.floor(0.5+x0+(y-y0)*(x2-x0)/(y2-y0))\n z02 = z0+(y-y0)*(z2-z0)/(y2-y0)\n if (x01 != x02)\n var slope = (z02-z01)/(x02-x01)\n else\n var slope = 0\n var x = x01 - dir\n while (x != x02) {\n x += dir\n var z = z01+slope*(x-x01)\n if (z > map[(h-1-y)*w+x]) {\n map[(h-1-y)*w+x] = z\n var iz = Math.floor(255*(z-zmin)/(zmax-zmin))\n buf[(h-1-y)*w*4+x*4+0] = iz\n buf[(h-1-y)*w*4+x*4+1] = iz\n buf[(h-1-y)*w*4+x*4+2] = iz\n }\n }\n }\n }\n }\n //\n // output the map\n //\n self.postMessage({imgbuffer:buf.buffer,mapbuffer:map.buffer},[buf.buffer,map.buffer])\n self.close()\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":"124.64802090317082","left":"1209.2725971321183","filename":"undefined","inputs":{},"outputs":{}},"0.21976500984768532":{"definition":"//\n// view path\n//\n// Neil Gershenfeld \n// (c) Massachusetts Institute of Technology 2019\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// todo:\n// erase and update new path\n// show depth info\n// show size\n// calculate camera far\n//\n// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'view path'\n//\n// initialization\n//\nvar init = function() {\n }\n//\n// inputs\n//\nvar inputs = {\n path:{type:'',\n event:function(evt){\n mod.path = evt.detail.path\n mod.name = evt.detail.name\n mod.dpi = evt.detail.dpi\n mod.width = evt.detail.width\n mod.height = evt.detail.height\n mod.depth = evt.detail.depth\n show_path_info()\n show_path()\n mods.fit(mod.div)\n outputs.path.event()\n }}}\n//\n// outputs\n//\nvar outputs = {\n path:{type:'',\n event:function(){\n cmd = {}\n cmd.path = mod.path\n cmd.name = mod.name\n cmd.dpi = mod.dpi\n cmd.width = mod.width\n cmd.height = mod.height\n mods.output(mod,'path',cmd)\n }}}\n//\n// interface\n//\nvar interface = function(div){\n mod.div = div\n //\n // info\n //\n var text = document.createTextNode('name: ')\n div.appendChild(text)\n mod.nametext = text\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('(mm)')\n div.appendChild(text)\n mod.mmtext = text\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('(in)')\n div.appendChild(text)\n mod.intext = text\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 open_view_window()\n })\n div.appendChild(btn)\n }\n//\n// local functions\n//\n// show_path_info\n//\nfunction show_path_info() {\n mod.nametext.nodeValue = 'name: '+mod.name\n var width = (25.4*mod.width/mod.dpi).toFixed(3)\n var height = (25.4*mod.height/mod.dpi).toFixed(3)\n var depth = (25.4*mod.depth/mod.dpi).toFixed(3)\n if (mod.depth == undefined)\n mod.mmtext.nodeValue = width+' x '+height+' (mm)'\n else\n mod.mmtext.nodeValue = width+' x '+height+' x '+depth+' (mm)'\n var width = (mod.width/mod.dpi).toFixed(3)\n var height = (mod.height/mod.dpi).toFixed(3)\n var depth = (mod.depth/mod.dpi).toFixed(3)\n if (mod.depth == undefined)\n mod.intext.nodeValue = width+' x '+height+' (in)'\n else\n mod.intext.nodeValue = width+' x '+height+' x '+depth+' (in)'\n mods.fit(mod.div)\n }\n//\n// show_path\n//\nfunction show_path() {\n var scene = mod.scene\n var camera = mod.camera\n var renderer = mod.renderer\n //\n // check if view window open\n //\n if (mod.win == undefined) {\n open_view_window()\n return\n }\n //\n // check for path\n //\n if (mod.path == undefined)\n return\n //\n // clear scene, leave camera\n //\n var length = scene.children.length\n for (var c = (length-1); c > 1; --c) {\n scene.remove(scene.children[c])\n }\n //\n // fit camera\n //\n mod.thetaxy = 0\n mod.thetaz = 0\n mod.r = mod.height/2\n mod.x0 = mod.width/2\n mod.y0 = mod.height/2\n camera.position.set(mod.x0,mod.y0,mod.r)\n camera.up = new THREE.Vector3(0,1,0)\n camera.lookAt(new THREE.Vector3(mod.x0,mod.y0,0))\n camera.updateProjectionMatrix()\n //\n // draw segments\n //\n var arrow_size = 1+mod.width/200\n var path = mod.path\n for (var segment = 0; segment < path.length; ++segment) {\n if (segment > 0)\n add_arrow(path[segment-1][path[segment-1].length-1],path[segment][0],0xff0000,arrow_size) \n for (var point = 1; point < path[segment].length; ++point) {\n add_arrow(path[segment][point-1],path[segment][point],0x0000ff,arrow_size)\n }\n }\n //\n // add axes\n //\n var length = mod.height/10\n add_arrow([0,0,0],[length,0,0],0xff0000,arrow_size)\n add_arrow([0,0,0],[0,length,0],0x00ff00,arrow_size)\n add_arrow([0,0,0],[0,0,length],0x0000ff,arrow_size)\n //\n // render\n //\n update()\n //\n // add_arrow\n //\n function add_arrow(start,stop,color,size) {\n var origin = new THREE.Vector3().fromArray(start)\n if (mod.depth == undefined)\n origin.z = 0\n var end = new THREE.Vector3().fromArray(stop)\n if (mod.depth == undefined)\n end.z = 0\n var length = new THREE.Vector3().subVectors(end,origin).length()\n if (length <= size) {\n add_line(origin,end,color)\n //length = 1.1*size\n return\n }\n var direction = new THREE.Vector3().subVectors(end,origin).normalize()\n var arrow = new THREE.ArrowHelper(direction,origin,length,color,size,size)\n scene.add(arrow)\n }\n //\n // add_line\n //\n function add_line(start,stop,colorhex) {\n var geometry = new THREE.Geometry()\n geometry.vertices.push(start,stop)\n var material = new THREE.LineBasicMaterial({color:colorhex})\n var line = new THREE.Line(geometry,material)\n scene.add(line)\n }\n //\n // update\n //\n function update() {\n renderer.render(scene,camera)\n }\n }\n//\n// open_view_window\n//\nfunction open_view_window() {\n //\n // open window\n //\n win = window.open('')\n mod.win = win\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// init_window\n//\nfunction init_window() {\n //document.write('<script type=\"text/javascript\">'+arg+'</script>')\n //document.close()\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 mod.win.close()\n mod.win = undefined\n })\n mod.win.document.body.appendChild(btn)\n //\n // label text\n //\n var text = win.document.createTextNode(' left: pan, right: rotate, scroll: zoom')\n mod.win.document.body.appendChild(text)\n //\n // GL container\n //\n mod.win.document.body.appendChild(document.createElement('br')) \n container = mod.win.document.createElement('div')\n container.style.overflow = 'hidden'\n mod.win.document.body.appendChild(container)\n //\n // event handlers\n //\n container.addEventListener('contextmenu',context_menu)\n container.addEventListener('mousedown',mouse_down)\n container.addEventListener('mouseup',mouse_up)\n container.addEventListener('mousemove',mouse_move)\n container.addEventListener('wheel',mouse_wheel)\n //\n // add scene\n //\n scene = new THREE.Scene()\n mod.scene = scene\n var width = mod.win.innerWidth\n var height = mod.win.innerHeight\n var aspect = width/height\n var near = 0.1\n var far = 1000000\n camera = new THREE.PerspectiveCamera(90,aspect,near,far)\n mod.camera = camera\n scene.add(camera)\n //\n // add renderer\n //\n renderer = new THREE.WebGLRenderer({antialias:true})\n mod.renderer = renderer\n renderer.setClearColor(0xffffff)\n renderer.setSize(width,height)\n container.appendChild(renderer.domElement)\n //\n // show the path if available\n //\n show_path()\n //\n // context_menu\n //\n function context_menu(evt) {\n evt.preventDefault()\n evt.stopPropagation()\n return (false)\n }\n //\n // mouse_down\n //\n function mouse_down(evt) {\n evt.preventDefault()\n evt.stopPropagation()\n mod.button = evt.button\n mod.x = evt.clientX\n mod.y = evt.clientY\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 // mouse_move\n //\n function mouse_move(evt) {\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/mod.win.innerHeight\n -Math.cos(mod.thetaz)*mod.width*dx/mod.win.innerWidth\n mod.y0 += \n Math.cos(mod.thetaz)*mod.height*dy/mod.win.innerHeight\n +Math.sin(mod.thetaz)*mod.width*dx/mod.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 renderer.render(scene,camera)\n }\n else if (mod.button == 2) {\n mod.thetaxy += dy/mod.win.innerHeight\n mod.thetaz += dx/mod.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 if (Math.cos(mod.thetaxy) > 0)\n camera.up = new THREE.Vector3(Math.sin(mod.thetaz),Math.cos(mod.thetaz),0)\n else\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 // mouse_wheel\n //\n function mouse_wheel(evt) {\n evt.preventDefault()\n evt.stopPropagation()\n var dy = evt.deltaY/mod.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 renderer.render(scene,camera)\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":"1051.330989940735","left":"1230.9648592659537","filename":"undefined","inputs":{},"outputs":{}},"0.5958662931535647":{"definition":"//\n// save file\n//\n// Neil Gershenfeld \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// closure\n//\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'save file'\n//\n// initialization\n//\nvar init = function() {\n }\n//\n// inputs\n//\nvar inputs = {\n file:{type:'object',\n event:function(evt){\n mod.name = evt.detail.name\n mod.contents = evt.detail.contents\n save_file()\n }}}\n//\n// outputs\n//\nvar outputs = {}\n//\n// interface\n//\nvar interface = function(div){\n mod.div = div\n //\n // info\n //\n var text = document.createTextNode('name:')\n div.appendChild(text)\n mod.nametext = text\n div.appendChild(document.createElement('br'))\n var text = document.createTextNode('size:')\n div.appendChild(text)\n mod.sizetext = text\n div.appendChild(document.createElement('br'))\n }\n//\n// local functions\n//\nfunction save_file() {\n var a = document.createElement('a')\n a.setAttribute('href','data:text/plain;charset=utf-8,'+ \n encodeURIComponent(mod.contents))\n a.setAttribute('download',mod.name)\n a.style.display = 'none'\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n mod.nametext.nodeValue = 'name: '+mod.name\n mods.fit(mod.div)\n mod.sizetext.nodeValue = 'size: '+mod.contents.length\n mods.fit(mod.div)\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":"830.7331133840215","left":"1251.9910798307683","filename":"undefined","inputs":{},"outputs":{}},"0.3062798763523076":{"definition":"//\n// Roland SRM-20 milling machine\n//\n// Neil Gershenfeld\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// closure\n//\n/*\nG-codes:\nG00X10.0\nG90 (absolute positioning)\nG21 (mm units)\n#.0 numbers\nG00 (positioning rapid move)\nG01 (linear motion)\nM03 (start spindle)\nM05 (stop spindle)\nF (feed rate mm/min, 6-1800)\n203.2 (X) x 152.4 (Y) x 60.5 (Z) mm \n*/\n(function(){\n//\n// module globals\n//\nvar mod = {}\n//\n// name\n//\nvar name = 'Roland SRM-20 milling machine'\n//\n// initialization\n//\nvar init = function() {\n mod.units = 100.0\n mod.speed.value = 4\n mod.ox.value = 10\n mod.oy.value = 10\n mod.oz.value = 10\n mod.jz.value = 2\n mod.hx.value = 0\n mod.hy.value = 152.4\n mod.hz.value = 60.5\n }\n//\n// inputs\n//\nvar inputs = {\n path:{type:'',\n event:function(evt){\n mod.name = evt.detail.name\n mod.path = evt.detail.path\n mod.dpi = evt.detail.dpi\n mod.width = evt.detail.width\n mod.height = evt.detail.height\n make_path()\n }}}\n//\n// outputs\n//\nvar outputs = {\n file:{type:'',\n event:function(obj){\n mods.output(mod,'file',obj)\n }}}\n//\n// interface\n//\nvar interface = function(div){\n mod.div = div\n //\n // speed\n //\n div.appendChild(document.createTextNode('speed: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n div.appendChild(input)\n mod.speed = input\n div.appendChild(document.createTextNode(' (mm/s)'))\n div.appendChild(document.createElement('br'))\n //\n // origin\n //\n div.appendChild(document.createTextNode('origin:'))\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode('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.createTextNode(' (mm)'))\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(' (mm)'))\n div.appendChild(document.createElement('br'))\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.createTextNode(' (mm)'))\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('move to origin')\n span.appendChild(text)\n btn.appendChild(span)\n btn.addEventListener('click',function(){\n var x0 = mod.units*parseFloat(mod.ox.value);\n var y0 = mod.units*parseFloat(mod.oy.value);\n var z0 = mod.units*parseFloat(mod.oz.value);\n var zjog = z0+mod.units*parseFloat(mod.jz.value);\n //\n // G-code version\n //\n /*\n str = '%\\n' // data start\n str += 'G90\\n' // absolute units\n str += 'G21\\n' // mm units\n str += 'G00Z30.0\\n' // move z\n str += 'M02\\n' // end of program\n */\n //\n // RML version\n //\n var str = \"PA;PA;VS10;!VZ10;!PZ0,\"+zjog+\";PU\"+x0+\",\"+y0+\";Z\"+x0+\",\"+y0+\",\"+z0+\";!MC0;\"+\"\\u0004\"\n //\n // send command\n //\n var obj = {}\n obj.type = 'command'\n obj.name = mod.name+'.rml'\n obj.contents = str\n outputs.file.event(obj)\n })\n div.appendChild(btn)\n div.appendChild(document.createElement('br'))\n //\n // jog\n //\n div.appendChild(document.createTextNode('jog height:'))\n div.appendChild(document.createElement('br'))\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.jz = input\n div.appendChild(document.createTextNode(' (mm)'))\n div.appendChild(document.createElement('br'))\n //\n // home\n //\n div.appendChild(document.createTextNode('home:'))\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode('x: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n div.appendChild(input)\n mod.hx = input\n div.appendChild(document.createTextNode(' (mm)'))\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.hy = input\n div.appendChild(document.createTextNode(' (mm)'))\n div.appendChild(document.createElement('br'))\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.hz = input\n div.appendChild(document.createTextNode(' (mm)'))\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('move to home')\n span.appendChild(text)\n btn.appendChild(span)\n btn.addEventListener('click',function(){\n var xhome = mod.units*parseFloat(mod.hx.value);\n var yhome = mod.units*parseFloat(mod.hy.value);\n var zhome = mod.units*parseFloat(mod.hz.value);\n //\n // G-code version\n //\n /*\n str = '%\\n' // data start\n str += 'G90\\n' // absolute units\n str += 'G21\\n' // mm units\n str += 'G00Z50.0\\n' // move z\n str += 'M02\\n' // end of program\n */\n //\n // RML version\n //\n var str = \"PA;PA;!PZ0,\"+zhome+\";PU\"+xhome+\",\"+yhome+\";!MC0;\"+\"\\u0004\"\n //\n // send command\n //\n var obj = {}\n obj.type = 'command'\n obj.name = mod.name+'.rml'\n obj.contents = str\n outputs.file.event(obj)\n })\n div.appendChild(btn)\n div.appendChild(document.createElement('br'))\n }\n//\n// local functions\n//\nfunction make_path() {\n var dx = 25.4*mod.width/mod.dpi\n var nx = mod.width\n var speed = parseFloat(mod.speed.value)\n var jog = parseFloat(mod.oz.value)+parseFloat(mod.jz.value)\n var ijog = Math.floor(mod.units*jog)\n var scale = mod.units*dx/(nx-1)\n var x0 = parseFloat(mod.ox.value)\n var y0 = parseFloat(mod.oy.value)\n var z0 = parseFloat(mod.oz.value)\n var xoffset = mod.units*x0\n var yoffset = mod.units*y0\n var zoffset = mod.units*z0\n var str = \"PA;PA;\" // plot absolute\n str += \"VS\"+speed+\";!VZ\"+speed+\";\"\n str += \"!PZ\"+0+\",\"+ijog+\";\" // set jog\n str += \"!MC1;\\n\" // turn motor on\n //\n // follow segments\n //\n for (var seg = 0; seg < mod.path.length; ++seg) {\n //\n // move up to starting point\n //\n x = xoffset+scale*mod.path[seg][0][0]\n y = yoffset+scale*mod.path[seg][0][1]\n str += \"PU\"+x.toFixed(0)+\",\"+y.toFixed(0)+\";\\n\"\n //\n // move down\n //\n z = zoffset+scale*mod.path[seg][0][2]\n str += \"Z\"+x.toFixed(0)+\",\"+y.toFixed(0)+\",\"+z.toFixed(0)+\";\\n\"\n for (var pt = 1; pt < mod.path[seg].length; ++pt) {\n //\n // move to next point\n //\n x = xoffset+scale*mod.path[seg][pt][0]\n y = yoffset+scale*mod.path[seg][pt][1]\n z = zoffset+scale*mod.path[seg][pt][2]\n str += \"Z\"+x.toFixed(0)+\",\"+y.toFixed(0)+\",\"+z.toFixed(0)+\";\\n\"\n }\n //\n // move up\n //\n str += \"PU\"+x.toFixed(0)+\",\"+y.toFixed(0)+\";\\n\"\n }\n //\n // turn off motor and move back\n //\n var xhome = mod.units*parseFloat(mod.hx.value)\n var yhome = mod.units*parseFloat(mod.hy.value)\n var zhome = mod.units*parseFloat(mod.hz.value)\n str += \"PA;PA;!PZ0,\"+zhome+\";PU\"+xhome+\",\"+yhome+\";!MC0;\"\n //\n // output string\n //\n var obj = {}\n obj.type = 'file'\n obj.name = mod.name+'.rml'\n obj.contents = str\n outputs.file.event(obj)\n }\n//\n// return values\n//\nreturn ({\n name:name,\n init:init,\n inputs:inputs,\n outputs:outputs,\n interface:interface\n })\n}())\n","top":"981.3223429160827","left":"677.9279893313669","filename":"modules/path/machines/Roland/milling/SRM-20","inputs":{},"outputs":{}},"0.1219393240810458":{"definition":"//\n// mill raster 3D\n//\n// Neil Gershenfeld 10/22/21\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 = 'mill raster 3D'\n//\n// initialization\n//\nvar init = function() {\n mod.dia_in.value = '0.125'\n mod.dia_mm.value = '3.175'\n mod.stepover.value = '0.5'\n mod.error.value = '0.001'\n }\n//\n// inputs\n//\nvar inputs = {\n map:{type:'',label:'height map',\n event:function(evt){\n mod.map = evt.detail.map\n mod.xmin = evt.detail.xmin\n mod.xmax = evt.detail.xmax\n mod.ymin = evt.detail.ymin\n mod.ymax = evt.detail.ymax\n mod.zmin = evt.detail.zmin\n mod.zmax = evt.detail.zmax\n mod.width = evt.detail.width\n mod.height = evt.detail.height\n mod.depth = Math.floor((mod.zmax-mod.zmin)*mod.width/(mod.xmax-mod.xmin))\n mod.mmunits = evt.detail.mmunits\n mod.dpi = mod.width/(mod.mmunits*(mod.xmax-mod.xmin)/25.4)\n var ctx = mod.img.getContext(\"2d\")\n ctx.canvas.width = mod.width\n ctx.canvas.height = mod.height\n }}}\n//\n// outputs\n//\nvar outputs = {\n toolpath:{type:'',\n event:function(){\n obj = {}\n obj.path = mod.path\n obj.name = \"mill raster 3D\"\n obj.dpi = mod.dpi\n obj.width = mod.width\n obj.height = mod.height\n obj.depth = mod.depth\n mods.output(mod,'toolpath',obj)\n }}}\n//\n// interface\n//\nvar interface = function(div){\n mod.div = div\n //\n // tool diameter\n //\n div.appendChild(document.createTextNode('tool diameter'))\n div.appendChild(document.createElement('br'))\n div.appendChild(document.createTextNode('mm: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('input',function(){\n mod.dia_in.value = parseFloat(mod.dia_mm.value)/25.4\n })\n div.appendChild(input)\n mod.dia_mm = input\n div.appendChild(document.createTextNode(' in: '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n input.addEventListener('input',function(){\n mod.dia_mm.value = parseFloat(mod.dia_in.value)*25.4\n })\n div.appendChild(input)\n mod.dia_in = input\n div.appendChild(document.createElement('br'))\n //\n // stepover\n //\n div.appendChild(document.createTextNode('stepover (0-1): '))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n div.appendChild(input)\n mod.stepover = input\n div.appendChild(document.createElement('br'))\n //\n // tool shape\n //\n div.appendChild(document.createTextNode('tool shape: '))\n var input = document.createElement('input')\n input.type = 'radio'\n input.name = mod.div.id+'shape'\n input.id = mod.div.id+'flatend'\n input.checked = true\n div.appendChild(input)\n mod.flatend= input\n div.appendChild(document.createTextNode('flat end'))\n div.appendChild(document.createElement('br'))\n //\n // direction \n //\n div.appendChild(document.createTextNode('direction: '))\n var input = document.createElement('input')\n input.type = 'checkbox'\n input.id = mod.div.id+'xz'\n input.checked = true\n div.appendChild(input)\n mod.dirxz = input\n div.appendChild(document.createTextNode('xz'))\n var input = document.createElement('input')\n input.type = 'checkbox'\n input.id = mod.div.id+'yz'\n input.checked = true\n div.appendChild(input)\n mod.diryz = input\n div.appendChild(document.createTextNode('yz'))\n div.appendChild(document.createElement('br'))\n //\n // fit error \n //\n div.appendChild(document.createTextNode('vector fit: '))\n //div.appendChild(document.createElement('br'))\n var input = document.createElement('input')\n input.type = 'text'\n input.size = 6\n div.appendChild(input)\n mod.error = input\n div.appendChild(document.createElement('br'))\n //\n // calculate\n //\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('calculate')\n mod.label = text\n span.appendChild(text)\n mod.labelspan = span\n btn.appendChild(span)\n btn.addEventListener('click',function(){\n mod.label.nodeValue = 'calculating'\n mod.labelspan.style.fontWeight = 'bold'\n calculate_path()\n })\n div.appendChild(btn)\n div.appendChild(document.createTextNode(' '))\n //\n // view\n //\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 var win = window.open('')\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 })\n win.document.body.appendChild(btn)\n win.document.body.appendChild(document.createElement('br'))\n var svg = document.getElementById(mod.div.id+'svg')\n var clone = svg.cloneNode(true)\n clone.setAttribute('width',mod.img.width)\n clone.setAttribute('height',mod.img.height)\n win.document.body.appendChild(clone)\n })\n div.appendChild(btn)\n div.appendChild(document.createElement('br'))\n //\n // on-screen SVG\n //\n var svgNS = \"http://www.w3.org/2000/svg\"\n var svg = document.createElementNS(svgNS,\"svg\")\n svg.setAttribute('id',mod.div.id+'svg')\n svg.setAttributeNS(\"http://www.w3.org/2000/xmlns/\",\n \"xmlns:xlink\",\"http://www.w3.org/1999/xlink\")\n svg.setAttribute('width',mods.ui.canvas)\n svg.setAttribute('height',mods.ui.canvas)\n svg.style.backgroundColor = 'rgb(255,255,255)'\n var g = document.createElementNS(svgNS,'g')\n g.setAttribute('id',mod.div.id+'g')\n svg.appendChild(g)\n div.appendChild(svg)\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//\n// local functions\n//\n// calculate path\n//\nfunction calculate_path() {\n var blob = new Blob(['('+calculate_path_worker.toString()+'())'])\n var url = window.URL.createObjectURL(blob)\n var webworker = new Worker(url)\n webworker.addEventListener('message',function(evt) {\n if (evt.data.type == \"progress\") {\n mod.label.nodeValue = evt.data.value\n return\n }\n //\n // webworker handler\n //\n mod.path = evt.data.path\n mod.label.nodeValue = 'calculate'\n mod.labelspan.style.fontWeight = 'normal'\n //\n // clear SVG\n //\n var svg = document.getElementById(mod.div.id+'svg')\n svg.setAttribute('viewBox',\"0 0 \"+(mod.width-1)+\" \"+(mod.height-1))\n var g = document.getElementById(mod.div.id+'g')\n svg.removeChild(g)\n var g = document.createElementNS('http://www.w3.org/2000/svg','g')\n g.setAttribute('id',mod.div.id+'g')\n svg.appendChild(g)\n //\n // plot path\n //\n for (var i = 1; i < mod.path[0].length; ++i) {\n var ixp = mod.path[0][i-1][0]\n var iyp = mod.height-1-mod.path[0][i-1][1]\n var izp = 0.1*mod.path[0][i-1][2]\n var ix = mod.path[0][i][0]\n var iy = mod.height-1-mod.path[0][i][1]\n var iz = 0.1*mod.path[0][i][2]\n var line = document.createElementNS(\n 'http://www.w3.org/2000/svg','line')\n line.setAttribute('stroke','black')\n line.setAttribute('stroke-width',1)\n line.setAttribute('stroke-linecap','round')\n line.setAttribute('x1',ixp)\n line.setAttribute('y1',iyp-izp)\n line.setAttribute('x2',ix)\n line.setAttribute('y2',iy-iz)\n g.appendChild(line)\n }\n //\n // output path\n //\n outputs.toolpath.event()\n })\n //\n // call webworker\n //\n webworker.postMessage({\n height:mod.height,width:mod.width,\n error:mod.error.value,\n xmin:mod.xmin,xmax:mod.xmax,\n ymin:mod.ymin,ymax:mod.ymax,\n zmin:mod.zmin,zmax:mod.zmax,\n diameter:mod.dia_mm.value,\n stepover:mod.stepover.value,\n mmunits: mod.mmunits,\n xz:mod.dirxz.checked,\n yz:mod.diryz.checked,\n map:mod.map})\n }\n//\n// calculate path worker\n//\nfunction calculate_path_worker() {\n self.addEventListener('message',function(evt) {\n var h = evt.data.height\n var w = evt.data.width\n var error = evt.data.error\n var xmin = evt.data.xmin\n var xmax = evt.data.xmax\n var ymin = evt.data.ymin\n var ymax = evt.data.ymax\n var zmin = evt.data.zmin\n var zmax = evt.data.zmax\n var map = evt.data.map\n var diameter = evt.data.diameter\n var stepover = evt.data.stepover\n var mmunits = evt.data.mmunits\n var step = Math.floor(stepover*diameter*w/(mmunits*(xmax-xmin)))\n var path = []\n //\n // construct tool offset\n //\n var toolsize = Math.floor(diameter*w/(mmunits*(xmax-xmin)))\n var tooloffset = new Float32Array(toolsize*toolsize)\n var toolmiddle = Math.floor(toolsize/2)\n for (var x = 0; x < toolsize; ++x)\n for (var y = 0; y < toolsize; ++y) {\n var r = Math.sqrt((x-toolmiddle)*(x-toolmiddle)+(y-toolmiddle)*(y-toolmiddle))\n if (r <= toolmiddle)\n tooloffset[y*toolsize+x] = 0\n else\n tooloffset[y*toolsize+x] = Number.MAX_VALUE\n }\n //\n // xz\n //\n if (evt.data.xz) {\n path.push([])\n var xstart = 0\n var ystart = h-1\n var zstart = Math.floor((map[ystart*w+xstart]-zmax)*w/(xmax-xmin))\n path[path.length-1].push([xstart,h-1-ystart,zstart])\n var xcur = 1\n var ycur = h-1\n var zcur = Math.floor((map[ycur*w+xcur]-zmax)*w/(xmax-xmin))\n var dx = 1\n var dy = 0\n while (1) {\n //\n // move to next point\n //\n xnext = xcur+dx\n ynext = ycur+dy\n if (ynext <= 0)\n //\n // done\n //\n break;\n //\n // find offset at next point\n //\n var znext = -Number.MAX_VALUE\n for (var xoffset = 0; xoffset < toolsize; ++xoffset)\n for (var yoffset = 0; yoffset < toolsize; ++yoffset) {\n var x = xnext+(xoffset-toolmiddle)\n var y = ynext+(yoffset-toolmiddle)\n var offset = tooloffset[yoffset*toolsize+xoffset]\n var z = Math.floor((map[y*w+x]-zmax)*w/(xmax-xmin))-offset\n if (z > znext)\n znext = z\n }\n //\n // vectorize\n //\n dxcur = xcur-xstart\n dycur = ycur-ystart\n dzcur = zcur-zstart\n dcur = Math.sqrt(dxcur*dxcur+dycur*dycur+dzcur*dzcur)\n nxcur = dxcur/dcur\n nycur = dycur/dcur\n nzcur = dzcur/dcur\n dxnext = xnext-xcur\n dynext = ynext-ycur\n dznext = znext-zcur\n dnext = Math.sqrt(dxnext*dxnext+dynext*dynext+dznext*dznext)\n nxnext = dxnext/dnext\n nynext = dynext/dnext\n nznext = dznext/dnext\n dot = nxcur*nxnext+nycur*nynext+nzcur*nznext\n if (dot <= (1-error)) {\n path[path.length-1].push([xcur,h-1-ycur,zcur])\n xstart = xcur\n ystart = ycur\n zstart = zcur\n }\n xcur = xnext\n ycur = ynext\n zcur = znext\n if (xcur == (w-1)) {\n if (dx == 1) {\n dx = 0\n dy = -step\n }\n else {\n dx = -1\n dy = 0\n }\n }\n else if (xcur == 0) {\n if (dx == -1) {\n dx = 0\n dy = -step\n }\n else {\n dx = 1\n dy = 0\n }\n }\n //\n // update progress\n //\n self.postMessage({type:'progress',value:ycur})\n }\n }\n //\n // yz\n //\n if (evt.data.yz) {\n path.push([])\n var xstart = w-1\n var ystart = 0\n var zstart = Math.floor((map[ystart*w+xstart]-zmax)*w/(xmax-xmin))\n path[path.length-1].push([xstart,h-1-ystart,zstart])\n var xcur = w-1\n var ycur = 1\n var zcur = Math.floor((map[ycur*w+xcur]-zmax)*w/(xmax-xmin))\n var dx = 0\n var dy = 1\n while (1) {\n //\n // move to next point\n //\n xnext = xcur+dx\n ynext = ycur+dy\n if (xnext <= 0)\n //\n // done\n //\n break;\n //\n // find offset at next point\n //\n var znext = -Number.MAX_VALUE\n for (var xoffset = 0; xoffset < toolsize; ++xoffset)\n for (var yoffset = 0; yoffset < toolsize; ++yoffset) {\n var x = xnext+(xoffset-toolmiddle)\n var y = ynext+(yoffset-toolmiddle)\n var offset = tooloffset[yoffset*toolsize+xoffset]\n var z = Math.floor((map[y*w+x]-zmax)*w/(xmax-xmin))-offset\n if (z > znext)\n znext = z\n }\n //\n // vectorize\n //\n dxcur = xcur-xstart\n dycur = ycur-ystart\n dzcur = zcur-zstart\n dcur = Math.sqrt(dxcur*dxcur+dycur*dycur+dzcur*dzcur)\n nxcur = dxcur/dcur\n nycur = dycur/dcur\n nzcur = dzcur/dcur\n dxnext = xnext-xcur\n dynext = ynext-ycur\n dznext = znext-zcur\n dnext = Math.sqrt(dxnext*dxnext+dynext*dynext+dznext*dznext)\n nxnext = dxnext/dnext\n nynext = dynext/dnext\n nznext = dznext/dnext\n dot = nxcur*nxnext+nycur*nynext+nzcur*nznext\n if (dot <= (1-error)) {\n path[path.length-1].push([xcur,h-1-ycur,zcur])\n xstart = xcur\n ystart = ycur\n zstart = zcur\n }\n xcur = xnext\n ycur = ynext\n zcur = znext\n if (ycur == (h-1)) {\n if (dy == 1) {\n dy = 0\n dx = -step\n }\n else {\n dy = -1\n dx = 0\n }\n }\n else if (ycur == 0) {\n if (dy == -1) {\n dy = 0\n dx = -step\n }\n else {\n dy = 1\n dx = 0\n }\n }\n //\n // update progress\n //\n self.postMessage({type:'progress',value:xcur})\n }\n }\n //\n // return\n //\n self.postMessage({type:'path',path:path})\n self.close()\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","top":"793.2645072647551","left":"258.7730903783895","filename":"modules/processes/mill/raster/3D","inputs":{},"outputs":{}}},"links":["{\"source\":\"{\\\"id\\\":\\\"0.0622871075904039\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"mesh\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.908940842104825\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"mesh\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.908940842104825\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"mesh\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.373975449262817\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"mesh\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.3062798763523076\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"file\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.5958662931535647\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"file\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.373975449262817\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"map\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.1219393240810458\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"map\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.1219393240810458\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"toolpath\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.21976500984768532\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"path\\\"}\"}","{\"source\":\"{\\\"id\\\":\\\"0.1219393240810458\\\",\\\"type\\\":\\\"outputs\\\",\\\"name\\\":\\\"toolpath\\\"}\",\"dest\":\"{\\\"id\\\":\\\"0.3062798763523076\\\",\\\"type\\\":\\\"inputs\\\",\\\"name\\\":\\\"path\\\"}\"}"]}
This diff is collapsed.
Click to expand it.
programs/machines/ShopBot/mill 3D stl
+
1
−
1
View file @
717bb43d
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment