Skip to content
Snippets Groups Projects
Commit 96cde867 authored by Neil Gershenfeld's avatar Neil Gershenfeld
Browse files

start 3D

parent 34216e42
Branches
No related tags found
No related merge requests found
......@@ -175,6 +175,7 @@
<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raster</i><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/processes/mill/raster/2.5D'>2.5D</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/processes/mill/raster/2D'>2D</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/processes/mill/raster/3D'>3D</a><br>
<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;read</i><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/read/png'>png</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/read/stl'>stl</a><br>
......
......@@ -144,6 +144,7 @@ module_label('   mill')
module_label(' raster')
module_menu(' 2.5D','modules/processes/mill/raster/2.5D')
module_menu(' 2D','modules/processes/mill/raster/2D')
module_menu(' 3D','modules/processes/mill/raster/3D')
module_label('read')
module_menu(' png','modules/read/png')
module_menu(' stl','modules/read/stl')
......
//
// mill raster 3D
//
// Neil Gershenfeld 1/18/20
//
// This work may be reproduced, modified, distributed, performed, and
// displayed for any purpose, but must acknowledge the mods
// project. Copyright is retained and must be preserved. The work is
// provided as is; no warranty is provided, and users accept all
// liability.
//
// closure
//
(function(){
//
// module globals
//
var mod = {}
//
// name
//
var name = 'mill raster 3D'
//
// initialization
//
var init = function() {
mod.dia_in.value = 0.0156
mod.dia_mm.value = 25.4*parseFloat(mod.dia_in.value)
mod.stepover.value = 0.5
}
//
// inputs
//
var inputs = {
map:{type:'',label:'height map',
event:function(evt){
mod.width = evt.detail.width
mod.height = evt.detail.height
var ctx = mod.img.getContext("2d")
ctx.canvas.width = mod.width
ctx.canvas.height = mod.height
console.log(mod.width)
console.log(mod.height)
}}}
//
// outputs
//
var outputs = {
toolpath:{type:'',
event:function(){
cmd = {}
cmd.path = mod.path
cmd.name = mod.name
cmd.dpi = mod.dpi
cmd.width = mod.width
cmd.height = mod.height
cmd.depth = mod.depth
mods.output(mod,'toolpath',cmd)
}}}
//
// interface
//
var interface = function(div){
mod.div = div
//
// tool diameter
//
div.appendChild(document.createTextNode('tool diameter'))
div.appendChild(document.createElement('br'))
div.appendChild(document.createTextNode('mm: '))
var input = document.createElement('input')
input.type = 'text'
input.size = 6
input.addEventListener('input',function(){
mod.dia_in.value = parseFloat(mod.dia_mm.value)/25.4
})
div.appendChild(input)
mod.dia_mm = input
div.appendChild(document.createTextNode(' in: '))
var input = document.createElement('input')
input.type = 'text'
input.size = 6
input.addEventListener('input',function(){
mod.dia_mm.value = parseFloat(mod.dia_in.value)*25.4
})
div.appendChild(input)
mod.dia_in = input
div.appendChild(document.createElement('br'))
//
// stepover
//
div.appendChild(document.createTextNode('stepover (0-1): '))
var input = document.createElement('input')
input.type = 'text'
input.size = 6
div.appendChild(input)
mod.stepover = input
div.appendChild(document.createElement('br'))
//
// tool shape
//
div.appendChild(document.createTextNode('tool shape: '))
div.appendChild(document.createTextNode('flat end'))
var input = document.createElement('input')
input.type = 'radio'
input.name = mod.div.id+'shape'
input.id = mod.div.id+'flatend'
input.checked = true
div.appendChild(input)
mod.flatend= input
div.appendChild(document.createElement('br'))
//
// direction
//
div.appendChild(document.createTextNode('direction: '))
div.appendChild(document.createTextNode('x'))
var input = document.createElement('input')
input.type = 'radio'
input.name = mod.div.id+'direction'
input.id = mod.div.id+'dirx'
input.checked = true
div.appendChild(input)
mod.dirx = input
div.appendChild(document.createElement('br'))
//
// calculate
//
var btn = document.createElement('button')
btn.style.padding = mods.ui.padding
btn.style.margin = 1
var span = document.createElement('span')
var text = document.createTextNode('calculate')
mod.label = text
span.appendChild(text)
mod.labelspan = span
btn.appendChild(span)
btn.addEventListener('click',function(){
mod.label.nodeValue = 'calculating'
mod.labelspan.style.fontWeight = 'bold'
mod.offset = 0.5
mod.offsetCount = 0
mod.path = []
clear_path()
outputs.diameter.event()
outputs.offset.event()
})
div.appendChild(btn)
div.appendChild(document.createTextNode(' '))
//
// view
//
var btn = document.createElement('button')
btn.style.padding = mods.ui.padding
btn.style.margin = 1
btn.appendChild(document.createTextNode('view'))
btn.addEventListener('click',function(){
var win = window.open('')
var btn = document.createElement('button')
btn.appendChild(document.createTextNode('close'))
btn.style.padding = mods.ui.padding
btn.style.margin = 1
btn.addEventListener('click',function(){
win.close()
})
win.document.body.appendChild(btn)
win.document.body.appendChild(document.createElement('br'))
var svg = document.getElementById(mod.div.id+'svg')
var clone = svg.cloneNode(true)
clone.setAttribute('width',mod.img.width)
clone.setAttribute('height',mod.img.height)
win.document.body.appendChild(clone)
})
div.appendChild(btn)
div.appendChild(document.createElement('br'))
//
// on-screen SVG
//
var svgNS = "http://www.w3.org/2000/svg"
var svg = document.createElementNS(svgNS,"svg")
svg.setAttribute('id',mod.div.id+'svg')
svg.setAttributeNS("http://www.w3.org/2000/xmlns/",
"xmlns:xlink","http://www.w3.org/1999/xlink")
svg.setAttribute('width',mods.ui.canvas)
svg.setAttribute('height',mods.ui.canvas)
svg.style.backgroundColor = 'rgb(255,255,255)'
var g = document.createElementNS(svgNS,'g')
g.setAttribute('id',mod.div.id+'g')
svg.appendChild(g)
div.appendChild(svg)
div.appendChild(document.createElement('br'))
//
// off-screen image canvas
//
var canvas = document.createElement('canvas')
mod.img = canvas
}
//
// local functions
//
// set_values
//
function set_values(settings) {
for (var s in settings) {
switch(s) {
case 'tool diameter (in)':
mod.dia_in.value = settings[s]
mod.dia_mm.value = parseFloat(mod.dia_in.value)*25.4
break
case 'cut depth (in)':
mod.cut_in.value = settings[s]
mod.cut_mm.value = parseFloat(mod.cut_in.value)*25.4
break
case 'max depth (in)':
mod.max_in.value = settings[s]
mod.max_mm.value = parseFloat(mod.max_in.value)*25.4
break
case 'offset number':
mod.number.value = settings[s]
break
}
}
}
//
// clear_path
//
function clear_path() {
var svg = document.getElementById(mod.div.id+'svg')
svg.setAttribute('viewBox',"0 0 "+(mod.img.width-1)+" "+(mod.img.height-1))
var g = document.getElementById(mod.div.id+'g')
svg.removeChild(g)
var g = document.createElementNS('http://www.w3.org/2000/svg','g')
g.setAttribute('id',mod.div.id+'g')
svg.appendChild(g)
}
//
// accumulate_path
// todo: replace inefficient insertion sort
// todo: move sort out of main thread
//
function accumulate_path(path) {
var forward = mod.forward.checked
var conventional = mod.conventional.checked
var sort = mod.sort.checked
for (var segnew = 0; segnew < path.length; ++segnew) {
if (conventional)
path[segnew].reverse()
if (mod.path.length == 0)
mod.path.splice(0,0,path[segnew])
else if (sort) {
var xnew = path[segnew][0][0]
var ynew = path[segnew][0][1]
var dmin = Number.MAX_VALUE
var segmin = -1
for (var segold = 0; segold < mod.path.length; ++segold) {
var xold = mod.path[segold][0][0]
var yold = mod.path[segold][0][1]
var dx = xnew-xold
var dy = ynew-yold
var d = Math.sqrt(dx*dx+dy*dy)
if (d < dmin) {
dmin = d
segmin = segold
}
}
if (forward)
mod.path.splice(segmin+1,0,path[segnew])
else
mod.path.splice(segmin,0,path[segnew])
}
else {
if (forward)
mod.path.splice(mod.path.length,0,path[segnew])
else
mod.path.splice(0,0,path[segnew])
}
}
}
//
// merge_path
//
function merge_path() {
var dmerge = mod.dpi*parseFloat(mod.merge.value)*parseFloat(mod.dia_in.value)
var seg = 0
while (seg < (mod.path.length-1)) {
var xold = mod.path[seg][mod.path[seg].length-1][0]
var yold = mod.path[seg][mod.path[seg].length-1][1]
var xnew = mod.path[seg+1][0][0]
var ynew = mod.path[seg+1][0][1]
var dx = xnew-xold
var dy = ynew-yold
var d = Math.sqrt(dx*dx+dy*dy)
if (d < dmerge)
mod.path.splice(seg,2,mod.path[seg].concat(mod.path[seg+1]))
else
seg += 1
}
}
//
// add_depth
//
function add_depth() {
var cut = parseFloat(mod.cut_in.value)
var max = parseFloat(mod.max_in.value)
var newpath = []
for (var seg = 0; seg < mod.path.length; ++seg) {
var depth = cut
if (mod.path[seg][0][0] == mod.path[seg][mod.path[seg].length-1][0]) {
var newseg = []
while (depth <= max) {
var idepth = -Math.round(mod.dpi*depth)
for (var pt = 0; pt < mod.path[seg].length; ++pt) {
var point = mod.path[seg][pt].concat(idepth)
newseg.splice(newseg.length,0,point)
}
if (depth == max)
break
depth += cut
if (depth > max)
depth = max
}
newpath.splice(newpath.length,0,newseg)
}
else {
var newseg = []
while (depth <= max) {
var idepth = -Math.round(mod.dpi*depth)
for (var pt = 0; pt < mod.path[seg].length; ++pt) {
var point = mod.path[seg][pt].concat(idepth)
newseg.splice(newseg.length,0,point)
}
newpath.splice(newpath.length,0,newseg)
newseg = []
if (depth == max)
break
depth += cut
if (depth > max)
depth = max
}
}
}
mod.path = newpath
mod.depth = Math.round(parseFloat(mod.max_in.value)*mod.dpi)
}
//
// draw_path
//
function draw_path(path) {
var g = document.getElementById(mod.div.id+'g')
var h = mod.img.height
var w = mod.img.width
var xend = null
var yend = null
//
// loop over segments
//
for (var segment = 0; segment < path.length; ++segment) {
if (path[segment].length > 1) {
//
// loop over points
//
for (var point = 1; point < path[segment].length; ++point) {
var line = document.createElementNS('http://www.w3.org/2000/svg','line')
line.setAttribute('stroke','black')
line.setAttribute('stroke-width',1)
line.setAttribute('stroke-linecap','round')
var x1 = path[segment][point-1][0]
var y1 = h-path[segment][point-1][1]-1
var x2 = path[segment][point][0]
var y2 = h-path[segment][point][1]-1
xend = x2
yend = y2
line.setAttribute('x1',x1)
line.setAttribute('y1',y1)
line.setAttribute('x2',x2)
line.setAttribute('y2',y2)
var dx = x2-x1
var dy = y2-y1
var d = Math.sqrt(dx*dx+dy*dy)
if (d > 0) {
nx = 6*dx/d
ny = 6*dy/d
var tx = 3*dy/d
var ty = -3*dx/d
g.appendChild(line)
triangle = document.createElementNS('http://www.w3.org/2000/svg','polygon')
triangle.setAttribute('points',x2+','+y2+' '+(x2-nx+tx)+','+(y2-ny+ty)
+' '+(x2-nx-tx)+','+(y2-ny-ty))
triangle.setAttribute('fill','black')
g.appendChild(triangle)
}
}
}
}
}
//
// draw_connections
//
function draw_connections() {
var g = document.getElementById(mod.div.id+'g')
var h = mod.img.height
var w = mod.img.width
//
// loop over segments
//
for (var segment = 1; segment < mod.path.length; ++segment) {
//
// draw connection from previous segment
//
var line = document.createElementNS('http://www.w3.org/2000/svg','line')
line.setAttribute('stroke','red')
line.setAttribute('stroke-width',1)
line.setAttribute('stroke-linecap','round')
var x1 = mod.path[segment-1][mod.path[segment-1].length-1][0]
var y1 = h-mod.path[segment-1][mod.path[segment-1].length-1][1]-1
var x2 = mod.path[segment][0][0]
var y2 = h-mod.path[segment][0][1]-1
line.setAttribute('x1',x1)
line.setAttribute('y1',y1)
line.setAttribute('x2',x2)
line.setAttribute('y2',y2)
var dx = x2-x1
var dy = y2-y1
var d = Math.sqrt(dx*dx+dy*dy)
if (d > 0) {
nx = 6*dx/d
ny = 6*dy/d
var tx = 3*dy/d
var ty = -3*dx/d
g.appendChild(line)
triangle = document.createElementNS('http://www.w3.org/2000/svg','polygon')
triangle.setAttribute('points',x2+','+y2+' '+(x2-nx+tx)+','+(y2-ny+ty)
+' '+(x2-nx-tx)+','+(y2-ny-ty))
triangle.setAttribute('fill','red')
g.appendChild(triangle)
}
}
}
//
// return values
//
return ({
mod:mod,
name:name,
init:init,
inputs:inputs,
outputs:outputs,
interface:interface
})
}())
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment