diff --git a/LOG.md b/LOG.md index f56fd6dcb719149e262228959298ce7f47b964e7..597ead7c358a14317dbe7445fd3e008811360d73 100644 --- a/LOG.md +++ b/LOG.md @@ -1,12 +1,27 @@ # Cuttlefish Dev Log / Scratch Notes +### Post Scuttlefish 2019 12 29 + +I'm not sure that I've merged the branches yet, but I think this exercise is largely done. The next big feats for me would be tightening up to a protocol, handling compound data types, etc. I think I can actually take these things on (save the sub-routing layer q / onion routing q) without fully breaking things apart. Compound data types at least I can implement for motion segments, and then the link state (protocol heavy / careful) work I can do just by working on links themselves. OK. + +Scratch notes from the month below... + +- pick state to maintain w/r/t connections-between-views and view sizes, etc. +- clean .clean() to not-nuke these things, +- consider refresh, what does it for these things? +- reloading ah hunk / probably refreshing the view when we have active DOM elements .rm's the native DOM elements, trouble trouble + +- large systems are still cumbersome in the browser - probably all of your calls to .position() per block are kinda yikes-like, could be semi-static offsets, calculated on redraw? +- there is also this serverside bug: your 'save' w/ a 'post' notification is too large, find out what the limit is on these, and maybe websocket them, or something like that? +- I think there is some chance this stepper bug is coming back: i.e the one where your drivers stall and then short other members of the system out. what's up with that? better gnd nets is a place to start, not stalling is also a place, and so is trying to use a simpler driver / the TMC2130, and look at stall protection diodes. + ### Dev Rebuilding 2019 12 10 OK, kind of last day to pin this together. I think to start, I'll add that button back to the link, then try to run the 'expandlink' routine again. Then I can see about my two views, and how to assemble these layers. Some progress here, I'm expanding links. To signal that ahn link has another-end, I have linkdef.contains ... -Last question is how to recover the view -> links relationships, i.e. the link.contains is our hookup at the graph level, then the link.contains.plane's existence determines whether / not we are rendering it. To transition between rendering and not-rendering, we create and destroy this plane. +Last question is how to recover the view -> links relationships, i.e. the link.contains is our hookup at the graph level, then the link.contains.plane's existence determines whether / not we are rendering it. To transition between rendering and not-rendering, we create and destroy this plane. ### Dev Rebuilding 2019 12 09 diff --git a/hunks/comm/swSVGSocket.js b/hunks/comm/swSVGSocket.js new file mode 100644 index 0000000000000000000000000000000000000000..50e7265b21e1c23995a88f90276516cc681afdd1 --- /dev/null +++ b/hunks/comm/swSVGSocket.js @@ -0,0 +1,132 @@ +/* +hunks/comm/swSVGSocket.js + +pipe from solidworks, delivers SVGs + +Jake Read at the Center for Bits and Atoms +Shawn Liu at Solidworks +(c) Massachusetts Institute of Technology 2019 + +This work may be reproduced, modified, distributed, performed, and +displayed for any purpose, but must acknowledge the squidworks and cuttlefish projects. +Copyright is retained and must be preserved. The work is provided as is; +no warranty is provided, and users accept all liability. +*/ + +import { + Hunkify, + Input, + Output, + State +} from '../hunks.js' + +export default function SWSVGClient() { + Hunkify(this) + + let dtout = this.output('string', 'svg', this) + + // lots! + let connectionStatus = this.state('boolean', 'connected', false) + let statusMessage = this.state('string', 'status', '...') + // conn, and sw conn, + let addressState = this.state('string', 'address', '127.0.0.1') + let portState = this.state('number', 'port', 8787) + let swId = this.state('string', 'swiD', '7772') + // svg extraction ... + let margin = this.state('number', 'margin (mm)', 10) + let includeInner = this.state('boolean', 'include inner faces', true) + + // this ws is a client, + let ws = {} + let url = `ws://127.0.0.1:${portState.value}` + + // we keep an outgoing set, + let outbuffer = new Array() + + // in case saved when 'open' + this.init = () => { + connectionStatus.set(false) + } + + connectionStatus.onChange = (value) => { + if(value){ + startWs() + } else { + ws.close() + } + } + + let updateSettings = () => { + // req. margin, + let marginCmd = { + modCmd: "SetMargin", + margin: Number(margin.value) + } + ws.send(JSON.stringify(marginCmd)) + // req inner / not-inner ... + let innerCmd = { + modCmd: "SetIncludeInner", + includeInner: includeInner.value + } + ws.send(JSON.stringify(innerCmd)) + ws.send('{"modCmd":"EnableSelectFaceNotify","selectFaceNotify":true}') + console.log('sent settings upd8') + } + + let startWs = () => { + // manager calls this once + // it is loaded and state is updated (from program) + url = 'ws://' + addressState.value + ':' + portState.value + this.log(`attempt start ws at ${url}`) + ws = new WebSocket(url) + ws.binaryType = "arraybuffer" + ws.onopen = (evt) => { + this.log('ws opened') + statusMessage.set('open') + connectionStatus.set(true) + // ack to shawn, + ws.send(JSON.stringify({ + modCmd: 'connect', + owner: 'mods', + id: swId.value + })) + // req. data? + updateSettings() + } + ws.onerror = (evt) => { + console.log('ws error:', evt) + statusMessage.set('error') + connectionStatus.set(false) + } + ws.onclose = (evt) => { + statusMessage.set('closed') + connectionStatus.set(false) + } + ws.onmessage = (message) => { + let mobj = JSON.parse(message.data) + if(true) console.log('sw-ws receives', mobj) + try{ + if(mobj.swType == 'FaceSVG'){ + outbuffer.push(mobj.data) + } + } catch (err) { + console.error('bad form on SW connect', err) + } + } + statusMessage.set('ws startup...') + } + + this.loop = () => { + // something like if(ws !== null && ws.isopen) + // if we have an open port, and have bytes to send downstream, + if (ws !== null && ws.readyState === 1) { + // could send, + } + + // check if we have outgoing to pass along + if (outbuffer.length > 0 && !dtout.io()) { + dtout.put(outbuffer.shift()) + } + + } +} diff --git a/hunks/image/svgToImageData.js b/hunks/image/svgToImageData.js new file mode 100644 index 0000000000000000000000000000000000000000..5f9c6aceb2f9c4601a578a15150184c08d931638 --- /dev/null +++ b/hunks/image/svgToImageData.js @@ -0,0 +1,122 @@ +/* +hunks/image/svgToImageData.js + +read svg, make image data. + +Jake Read at the Center for Bits and Atoms +Neil Gershenfeld at the CBA +(c) Massachusetts Institute of Technology 2019 + +This work may be reproduced, modified, distributed, performed, and +displayed for any purpose, but must acknowledge the squidworks and cuttlefish projects. +Copyright is retained and must be preserved. The work is provided as is; +no warranty is provided, and users accept all liability. +*/ + +import { + Hunkify, + Input, + Output, + State +} from '../hunks.js' + +// ahn test string ... +let svgString = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"100.80402657534\" height=\"151.75086719281\" viewBox=\"0 0 0.0284491370844639 0.0428274680101977\" style=\"background:black\"><path d=\" M 0,0.0328274680101977 L 0,0 L 0.00842724217606665,0 L 0.00842724217606665,0.005 L 0.0134272421760667,0.005 L 0.0134272421760667,0 L 0.0184491370844639,0 L 0.0184491370844639,0.0017 L 0.0151272421760667,0.0017 L 0.0151272421760667,0.0067 L 0.00842724217606665,0.0067 L 0.00842724217606665,0.0328274680101977 L 0,0.0328274680101977\" style=\"fill:#ffffff;fill-rule:evenodd;\" transform=\"translate(0.005 0.0378274680101977), scale(1, -1)\" /></svg>" + +export default function svgToImageData() { + Hunkify(this) + // 'string' 'input', get it? + let strin = this.input('string', 'svg') + let imgOut = this.output('ImageData', 'image') + let width = this.output('number', 'width (mm)') + let dpi = this.state('number', 'dpi', 300) + // to manipulate full scale: + let vcanvas = document.createElement('canvas') + let haveImageUpdate = false + + // ... getsize, draw, fill ? + let getSize = (svg) => { + // where 'svg' is some string, we return width, height, units + let i = svg.indexOf("width") + if (i == -1) { + return ({ + width: 1, + height: 1, + units: 90 + }) + } else { + var i1 = svg.indexOf("\"", i + 1) + var i2 = svg.indexOf("\"", i1 + 1) + var width = svg.substring(i1 + 1, i2) + i = svg.indexOf("height") + i1 = svg.indexOf("\"", i + 1) + i2 = svg.indexOf("\"", i1 + 1) + var height = svg.substring(i1 + 1, i2) + let ih = svg.indexOf("height") + let units = 0 + if (width.indexOf("px") != -1) { + width = width.slice(0, -2) + height = height.slice(0, -2) + units = 90 + } else if (width.indexOf("mm") != -1) { + width = width.slice(0, -2) + height = height.slice(0, -2) + units = 25.4 + } else if (width.indexOf("cm") != -1) { + width = width.slice(0, -2) + height = height.slice(0, -2) + units = 2.54 + } else if (width.indexOf("in") != -1) { + width = width.slice(0, -2) + height = height.slice(0, -2) + units = 1 + } else { + units = 90 + } + return ({ + width: width, + height: height, + units: units + }) + } + } + + let loadImage = (svg, size) => { + // btoa converts str. to base 64 + let src = "data:image/svg+xml;base64," + window.btoa(svg) + let img = new Image() + img.setAttribute('src', src) + let width = size.width * dpi.value / size.units + let height = size.height * dpi.value / size.units + img.onload = () => { + // new vcanvas always, + vcanvas = document.createElement('canvas') + vcanvas.width = width + vcanvas.height = height + let ctx = vcanvas.getContext('2d') + ctx.drawImage(img, 0, 0, width, height) + // now we are set, + haveImageUpdate = true + } + } + + let test = this.state('boolean', 'test', false) + test.onChange = (value) => { + let size = getSize(svgString) + loadImage(svgString, size) + test.set(false) + } + + this.loop = () => { + if(strin.io() && !haveImageUpdate){ + let str = strin.get() + let size = getSize(str) + loadImage(str, size) + } + if (haveImageUpdate && !imgOut.io() && !width.io()) { + imgOut.put(vcanvas.getContext('2d').getImageData(0, 0, vcanvas.width, vcanvas.height)) + width.put(vcanvas.width * 25.4/dpi.value) + haveImageUpdate = false + } + } +} diff --git a/hunks/interface/array.js b/hunks/interface/array.js index d305e6ad8b6b0bf91ac7d2c5903c0f7086e848f1..5541f08e0ef048c27bbe7fc1bddaf5cd37645a0d 100644 --- a/hunks/interface/array.js +++ b/hunks/interface/array.js @@ -24,16 +24,7 @@ export default function Number() { let op = this.output('array', 'arr') let opv = this.state('string', 'csv', '0, 0, 0') - // as is tradition, - this.dom = {} - - this.init = () => { - // manager calls this once - // it is loaded and state is updated (from program) - this.dom = $('<div>').get(0) - //this.dom = document.createElement('div') - } - + // str -> arr (nums) let convert = (str) => { let arr = opv.value.split(',') for(let i = 0; i < arr.length; i ++){ @@ -42,22 +33,22 @@ export default function Number() { return arr } - this.onload = () => { - let contact = $('<div>').addClass('btn').append('! shipment !').get(0) - $(this.dom).append(contact) - contact.addEventListener('click', (evt) => { + let dom = this.document() + let contact = $('<div>').addClass('btn').append('! ship it !').get(0) + contact.addEventListener('click', (evt) => { + if(op.io()){ + console.warn("array attempts to push to occupied output") + } else { let arr = convert(opv.value) - if(!op.io()){ - op.put(arr) - } else { - console.warn('this output is blocked') - } - }) - } + op.put(arr) + } + }) + $(dom).append(contact) this.loop = () => { if(ip.io() && !op.io()){ let str = ip.get() + // upd8 the state for this, as well... opv.set(str) let arr = convert(str) op.put(arr) diff --git a/hunks/statemachines/saturn.js b/hunks/statemachines/saturn.js index e47e5cdeadcc2b0467c3b6c9d07f424c258db832..086419f12eb919a9ccef74fd6f271c8e07486c4e 100644 --- a/hunks/statemachines/saturn.js +++ b/hunks/statemachines/saturn.js @@ -62,8 +62,8 @@ export default function Saturn() { accelState.onChange = (val) => { if(val > 30){ val = 30 - } else if (val < 2){ - val = 2 + } else if (val < 0.5){ + val = 0.5 } accelState.set(val) accel = accelState.value