From 42c0d46b29f92c478ee923801ea4aaf0d3cbf371 Mon Sep 17 00:00:00 2001
From: Jake Read <jake.read@cba.mit.edu>
Date: Wed, 30 Oct 2019 14:16:53 -0400
Subject: [PATCH] add dpi to images

---
 hunks/adhoc/saturn.js                         |  84 +++----
 hunks/adhoc/tpath.js                          |   9 +-
 hunks/image/readpng.js                        |  84 +++++--
 hunks/interface/threejs_ghost.js              |   4 +-
 save/contexts/cuttlefish/ghost-50ms.json      | 212 ++++++++++++++++++
 save/contexts/cuttlefish/sat-baretest.json    | 198 ++++++++++++++++
 save/contexts/cuttlefish/saturn-purebare.json | 117 ++++++++++
 7 files changed, 635 insertions(+), 73 deletions(-)
 create mode 100644 save/contexts/cuttlefish/ghost-50ms.json
 create mode 100644 save/contexts/cuttlefish/sat-baretest.json
 create mode 100644 save/contexts/cuttlefish/saturn-purebare.json

diff --git a/hunks/adhoc/saturn.js b/hunks/adhoc/saturn.js
index 9412772..1c5f937 100644
--- a/hunks/adhoc/saturn.js
+++ b/hunks/adhoc/saturn.js
@@ -37,9 +37,9 @@ export default function Saturn() {
   let outy = this.output('number', 'outy')
   let outz = this.output('number', 'outz')
   let outp = this.output('array', 'posn')
-  let period = 0.050 // his.state('number', 'period', 50) // in ms,
+  let period = 0.100 // his.state('number', 'period', 50) // in ms,
 
-  let allclear = () => {
+  let allClear = () => {
     return (!outx.io() && !outy.io() && !outz.io())
   }
 
@@ -51,14 +51,17 @@ export default function Saturn() {
 
   // settings,
   let deviation = 0.1 // virtual radius to junction about
-  let accel = 10 // units/s/s
+  let accel = 980 // units/s/s (9.8m/s/s, 9800mm/s/s is 1G)
   let minSpeed = 0.01 // conspicuous, to debug for tails (indexing)
 
   // current states,
-  let cruise = 10 // target, (units/s)
+  let cruise = 200 // target, (units/s)
   let speed = minSpeed // currently
   let posUpdated = false
 
+  // we nasty,
+  let spmm = 200
+
   let jd = (speeds, debug) => {
     //console.log('positions', positions)
     let calcJunctionSpeed = (p0, p1, p2, jd) => {
@@ -437,33 +440,9 @@ export default function Saturn() {
     return blocks
   }
 
-  /*
-    let calculateNextIncrement = () => {
-      // for now, straightforward: current position w/r/t positions,
-      // increment is this posn -> next target, at rate ...
-      // for simplicity, we can assume that we're always going from where we're at to the [1]th point in the positions,
-      let vect = [0, 0, 0]
-      let dist = vDist(position, positions[0])
-      vect.forEach((axis, i) => {
-        vect[i] = (positions[0][i] - position[i]) / dist
-      })
-      // easy increment is just this vector * rate / period
-      let timeSeg = [0, 0, 0]
-      timeSeg.forEach((axis, i) => {
-        timeSeg[i] = vect[i] * (cruise / period)
-      })
-      // now, is this a step-over ? some fast-slow-math for this:
-      let np = vSum(position, timeSeg)
-      if (vDist(np, position) > vDist(position, positions[0])) {
-        // ts is just to get us exactly to it ..
-        timeSeg.forEach((axis, i) => {
-          timeSeg[i] = positions[0][i] - position[i]
-        })
-        positions.shift()
-      }
-      return timeSeg
-    }
-  */
+  let blockOnce = true
+  let blocks = []
+  let posNow = []
 
   this.loop = () => {
     // loading new points,
@@ -482,10 +461,11 @@ export default function Saturn() {
         console.warn('error caught at saturn input', err)
       }
     }
-    //if (allclear() && positions.length > 32) {
+    //if (allClear() && positions.length > 32) {
     // first we get all move final v's by jd:
     // we jd,
-    if (positions.length > 63) {
+    if (positions.length > positionsBufferSize - 1 && blockOnce) {
+      blockOnce = false
       // ok, here's the lookahead routine:
       console.time('lookahead')
       // positions[] is global, speeds is generated now
@@ -521,37 +501,33 @@ export default function Saturn() {
       console.timeLog('lookahead')
       console.log(`have ${ramps.length} ramps for ${positions.length} positions`)
       // should see about writing out motion blocks:
-      let blocks = blockPass(ramps, true)
+      blocks = blockPass(ramps, true)
       console.log(`have ${blocks.length} blocks for ${ramps.length} ramps`)
-      console.timeEnd('lookahead') // 49ms ... to write ~ 3k blocks from 145 ramps from 64 positions 
+      console.timeEnd('lookahead') // 49ms ... to write ~ 3k blocks from 145 ramps from 64 positions
       // OK: I think this is it... I'll wrap the loop again to do this once, then write those blocks out at the
       // flowcontrol'd interval... and see how it looks. this is maybe even enough: if steppers just make these counts
       // of steps, distance is preserved, but some jerk every 50ms... interpolation next
       // run once,
-      throw new Error('halt')
+      //throw new Error('halt')
     }
-    /*
-      // this is our major timestep, and should happen only once-every-segment
-      // positions length reads @ 26, but NaN ??
-      // do check ... if anything is NaN, print all positions, OK. maybe reference problem?
-      console.log(positions.length)
-      // we have items in the positions,
-      // we should calculate an ideal trajectory from our current position and speed
-      // probably recalculating the whole thing, and then send that out...
-      let ts = calculateNextIncrement()
-      //console.log('time seg\t', ts)
-      position = vSum(position, ts)
+
+    if(blocks.length > 0 && allClear()){
+      let bl = blocks.shift()
+      //console.log('block', bl)
+      let dist = vDist(bl[0], bl[1])
+      console.log(dist.toFixed(4))
+      // to gate,
+      outx.put(1)
+      outy.put(1)
+      outz.put(1)
+      // and,
+      posNow = vScalar(bl[0], spmm)
       posUpdated = true
-      // send 'em
-      outx.put(ts[0])
-      outy.put(ts[1])
-      outz.put(ts[2])
     }
+
     if (!outp.io() && posUpdated) {
-      outp.put(position)
+      outp.put(posNow)
       posUpdated = false
     }
-    */
-    //}
   }
 }
diff --git a/hunks/adhoc/tpath.js b/hunks/adhoc/tpath.js
index 67af260..5ed840a 100644
--- a/hunks/adhoc/tpath.js
+++ b/hunks/adhoc/tpath.js
@@ -14,7 +14,10 @@ import {
 // example-path-long.js also exists...
 // example-path-small.js ...
 // example-path-sl2.js
-import * as expath from '../../test_files/example-path-sl2.js' 
+import * as expath from '../../test_files/example-path-sl2.js'
+import { vScalar } from '../../libs/smallvectors.js'
+
+let dpi = 600
 
 export default function TPFCOUT(){
   Hunkify(this)
@@ -22,7 +25,7 @@ export default function TPFCOUT(){
   // copy this in au manuel
   let ogpath = expath.default.arr
   let path = []
-  let go = true
+  let go = false
 
   let outPosn = this.output('array', 'position')
   let outReset = this.state('boolean', 'reset', false)
@@ -40,7 +43,7 @@ export default function TPFCOUT(){
   this.loop = () => {
     if(path.length > 0 && go){
       if(!outPosn.io()){
-        outPosn.put(path.shift())
+        outPosn.put(vScalar(path.shift(), 600 / 25.4))
       }
     }
   }
diff --git a/hunks/image/readpng.js b/hunks/image/readpng.js
index bdab6a7..a1d5358 100644
--- a/hunks/image/readpng.js
+++ b/hunks/image/readpng.js
@@ -13,12 +13,14 @@ export default function UploadPNG() {
   let idealWidth = 395; // (want to pull width out of some API for this.dom - element width .. have resize..)
   let localImageInfo = null;
   let imageUpdated = false;
+  let localDpi = null
+  let dpiUpdated = false
 
   // it looks like 'RGBA' types are actually ImageData objects,
   // https://developer.mozilla.org/en-US/docs/Web/API/ImageData
   // since we will be using these in canvas-contexts, makes sense to just use these types
-  const imageOut = new Output("ImageData", "image", this);
-  this.outputs.push(imageOut);
+  let imageOut = this.output("ImageData", "image")
+  let dpiOut = this.output('number', 'dpi')
 
   // as a hack, we can use boolean state variables as a button: they have handy callbacks...
   const trig = new State("boolean", "release", false);
@@ -26,7 +28,8 @@ export default function UploadPNG() {
   trig.onChange = (value) => {
     // I'll set this flag so that we will release image info on the next loop
     // if any is available,
-    imageUpdated = true;
+    imageUpdated = true
+    dpiUpdated = true
   };
 
   // names for elements,
@@ -40,16 +43,16 @@ export default function UploadPNG() {
 
   //import
   const png_read_handler = e => {
-    const reader = new FileReader();
-
+    const imageReader = new FileReader();
     const files = e.target.files;
     const file = files[0];
-
     const img = new Image();
     img.file = file;
-
-    const loader = aImg => e => {
-      aImg.src = e.target.result;
+    const imageLoader = aImg => e => {
+      // binary:
+      let raw = e.target.result
+      // useful:
+      aImg.src = raw;
       aImg.onload = () => {
         // OK: sometimes this image is *way too big* to dump into the DOM,
         // so we write it into a new and virtual canvas that we won't render:
@@ -61,7 +64,6 @@ export default function UploadPNG() {
         // great, now we can use this to pull normalized ImageData information, this is what we pass around:
         localImageInfo = vContext.getImageData(0, 0, aImg.width, aImg.height);
         imageUpdated = true;
-
         // now we can draw something:
         const canvas = document.getElementById(`${canvasUid}`);
         // we'll want to shrink the whole thing ... or enlarge,
@@ -76,8 +78,58 @@ export default function UploadPNG() {
         ctx.drawImage(aImg, 0, 0);
       };
     };
-    reader.onload = loader(img);
-    reader.readAsDataURL(file);
+    imageReader.onload = imageLoader(img);
+    imageReader.readAsDataURL(file);
+    // and ah data version...
+    const headerLoader = (event) => {
+      console.log('e', event.target.result)
+      // https://gitlab.cba.mit.edu/pub/mods/blob/master/modules/read/png
+      //
+      // get DPI
+      //
+      // 8 header
+      // 4 len, 4 type, data, 4 crc
+      // pHYs 4 ppx, 4 ppy, 1 unit: 0 ?, 1 meter
+      // IEND
+      //
+      var units = 0
+      var ppx = 0
+      var ppy = 0
+      var dpi = 0
+      var buf = event.target.result
+      var view = new DataView(buf)
+      var ptr = 8
+      if (!((view.getUint8(1) == 80) && (view.getUint8(2) == 78) && (view.getUint8(3) == 71))) {
+        console.warn("error: PNG header not found")
+        return
+      }
+      while (1) {
+        var length = view.getUint32(ptr)
+        ptr += 4
+        var type = String.fromCharCode(
+          view.getUint8(ptr), view.getUint8(ptr + 1),
+          view.getUint8(ptr + 2), view.getUint8(ptr + 3))
+        ptr += 4
+        if (type == "pHYs") {
+          ppx = view.getUint32(ptr)
+          ppy = view.getUint32(ptr + 4)
+          units = view.getUint8(ptr + 8)
+        }
+        if (type == "IEND")
+          break
+        ptr += length + 4
+      }
+      if (units == 0) {
+        console.warn("no PNG units not found, assuming 72 DPI")
+        ppx = 72 * 1000 / 25.4
+      }
+      localDpi = ppx * 25.4 / 1000
+      dpiUpdated = true
+      console.log('dpi', localDpi)
+    }
+    let headerReader = new FileReader()
+    headerReader.onload = headerLoader
+    headerReader.readAsArrayBuffer(file)
   };
 
   this.onload = () => {
@@ -85,7 +137,7 @@ export default function UploadPNG() {
     $(this.dom).append(target);
     // to name unique DOM elements, if we want to access them later using 'get element' methods,
     // we can prepend the hunk's name (which is unique)
-    const view = html`
+    const view = html `
       <style>
         #${inputItemUid} {
           margin: 5px;
@@ -113,9 +165,13 @@ export default function UploadPNG() {
   this.loop = () => {
     // we release data if we have any, if it's been updated, and if the output is clear:
     if (localImageInfo && imageUpdated && !imageOut.io()) {
-      console.log(`${this.name} puts:`, localImageInfo);
+      //console.log(`${this.name} puts:`, localImageInfo);
       imageUpdated = false;
       imageOut.put(localImageInfo);
     }
+    if(localDpi && dpiUpdated && !dpiOut.io()){
+      dpiUpdated = false
+      dpiOut.put(localDpi)
+    }
   };
 }
diff --git a/hunks/interface/threejs_ghost.js b/hunks/interface/threejs_ghost.js
index cd38fdd..acd522d 100644
--- a/hunks/interface/threejs_ghost.js
+++ b/hunks/interface/threejs_ghost.js
@@ -31,8 +31,8 @@ export default function ThreeGhosts(){
   let height = 1000
   let lineWidth = 10
   let geometry = new THREE.Geometry()
-  for(let i = 32; i > 0; i --){
-    geometry.vertices.push(new THREE.Vector3(10*i, 10*i, 10*i))
+  for(let i = 512; i > 0; i --){
+    geometry.vertices.push(new THREE.Vector3(0.5*i, 0.5*i, 0.5*i))
   }
 
   let updatePts = []
diff --git a/save/contexts/cuttlefish/ghost-50ms.json b/save/contexts/cuttlefish/ghost-50ms.json
new file mode 100644
index 0000000..5833f31
--- /dev/null
+++ b/save/contexts/cuttlefish/ghost-50ms.json
@@ -0,0 +1,212 @@
+{
+  "interpreterName": "cuttlefish",
+  "interpreterVersion": "v0.1",
+  "hunks": [
+    {
+      "type": "manager",
+      "name": "nrol",
+      "inputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray",
+          "connections": [
+            {
+              "inHunkIndex": "1",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "view",
+      "name": "tlview",
+      "inputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray",
+          "connections": [
+            {
+              "inHunkIndex": "0",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "adhoc/saturn",
+      "name": "adhoc/saturn_2",
+      "inputs": [
+        {
+          "name": "posn",
+          "type": "array"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "outx",
+          "type": "number",
+          "connections": [
+            {
+              "inHunkIndex": "4",
+              "inHunkInput": "0"
+            }
+          ]
+        },
+        {
+          "name": "outy",
+          "type": "number",
+          "connections": [
+            {
+              "inHunkIndex": "5",
+              "inHunkInput": "0"
+            }
+          ]
+        },
+        {
+          "name": "outz",
+          "type": "number",
+          "connections": [
+            {
+              "inHunkIndex": "6",
+              "inHunkInput": "0"
+            }
+          ]
+        },
+        {
+          "name": "posn",
+          "type": "array",
+          "connections": [
+            {
+              "inHunkIndex": "7",
+              "inHunkInput": "0"
+            },
+            {
+              "inHunkIndex": "8",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "adhoc/tpath",
+      "name": "adhoc/tpath_3",
+      "outputs": [
+        {
+          "name": "position",
+          "type": "array",
+          "connections": [
+            {
+              "inHunkIndex": "2",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ],
+      "states": [
+        {
+          "name": "reset",
+          "type": "boolean",
+          "value": "false"
+        }
+      ]
+    },
+    {
+      "type": "adhoc/consumer",
+      "name": "adhoc/consumer_4",
+      "inputs": [
+        {
+          "name": "takes",
+          "type": "number"
+        }
+      ],
+      "states": [
+        {
+          "name": "period",
+          "type": "number",
+          "value": "50"
+        }
+      ]
+    },
+    {
+      "type": "adhoc/consumer",
+      "name": "adhoc/consumer_5",
+      "inputs": [
+        {
+          "name": "takes",
+          "type": "number"
+        }
+      ],
+      "states": [
+        {
+          "name": "period",
+          "type": "number",
+          "value": "50"
+        }
+      ]
+    },
+    {
+      "type": "adhoc/consumer",
+      "name": "adhoc/consumer_6",
+      "inputs": [
+        {
+          "name": "takes",
+          "type": "number"
+        }
+      ],
+      "states": [
+        {
+          "name": "period",
+          "type": "number",
+          "value": "50"
+        }
+      ]
+    },
+    {
+      "type": "data/logger",
+      "name": "data/logger_7",
+      "inputs": [
+        {
+          "name": "tolog",
+          "type": "reference"
+        }
+      ],
+      "states": [
+        {
+          "name": "prefix",
+          "type": "string",
+          "value": "LOG:"
+        },
+        {
+          "name": "console",
+          "type": "boolean",
+          "value": "false"
+        }
+      ]
+    },
+    {
+      "type": "interface/threejs_ghost",
+      "name": "interface/threejs_ghost_9",
+      "inputs": [
+        {
+          "name": "point",
+          "type": "array"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/save/contexts/cuttlefish/sat-baretest.json b/save/contexts/cuttlefish/sat-baretest.json
new file mode 100644
index 0000000..f84a645
--- /dev/null
+++ b/save/contexts/cuttlefish/sat-baretest.json
@@ -0,0 +1,198 @@
+{
+  "interpreterName": "cuttlefish",
+  "interpreterVersion": "v0.1",
+  "hunks": [
+    {
+      "type": "manager",
+      "name": "nrol",
+      "inputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray",
+          "connections": [
+            {
+              "inHunkIndex": "1",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "view",
+      "name": "tlview",
+      "inputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray",
+          "connections": [
+            {
+              "inHunkIndex": "0",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "adhoc/saturn",
+      "name": "adhoc/saturn_2",
+      "inputs": [
+        {
+          "name": "posn",
+          "type": "array"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "outx",
+          "type": "number",
+          "connections": [
+            {
+              "inHunkIndex": "4",
+              "inHunkInput": "0"
+            }
+          ]
+        },
+        {
+          "name": "outy",
+          "type": "number",
+          "connections": [
+            {
+              "inHunkIndex": "5",
+              "inHunkInput": "0"
+            }
+          ]
+        },
+        {
+          "name": "outz",
+          "type": "number",
+          "connections": [
+            {
+              "inHunkIndex": "6",
+              "inHunkInput": "0"
+            }
+          ]
+        },
+        {
+          "name": "posn",
+          "type": "array",
+          "connections": [
+            {
+              "inHunkIndex": "7",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "adhoc/tpath",
+      "name": "adhoc/tpath_3",
+      "outputs": [
+        {
+          "name": "position",
+          "type": "array",
+          "connections": [
+            {
+              "inHunkIndex": "2",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ],
+      "states": [
+        {
+          "name": "reset",
+          "type": "boolean",
+          "value": "false"
+        }
+      ]
+    },
+    {
+      "type": "adhoc/consumer",
+      "name": "adhoc/consumer_4",
+      "inputs": [
+        {
+          "name": "takes",
+          "type": "number"
+        }
+      ],
+      "states": [
+        {
+          "name": "period",
+          "type": "number",
+          "value": "50"
+        }
+      ]
+    },
+    {
+      "type": "adhoc/consumer",
+      "name": "adhoc/consumer_5",
+      "inputs": [
+        {
+          "name": "takes",
+          "type": "number"
+        }
+      ],
+      "states": [
+        {
+          "name": "period",
+          "type": "number",
+          "value": "50"
+        }
+      ]
+    },
+    {
+      "type": "adhoc/consumer",
+      "name": "adhoc/consumer_6",
+      "inputs": [
+        {
+          "name": "takes",
+          "type": "number"
+        }
+      ],
+      "states": [
+        {
+          "name": "period",
+          "type": "number",
+          "value": "50"
+        }
+      ]
+    },
+    {
+      "type": "data/logger",
+      "name": "data/logger_7",
+      "inputs": [
+        {
+          "name": "tolog",
+          "type": "reference"
+        }
+      ],
+      "states": [
+        {
+          "name": "prefix",
+          "type": "string",
+          "value": "LOG:"
+        },
+        {
+          "name": "console",
+          "type": "boolean",
+          "value": "false"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/save/contexts/cuttlefish/saturn-purebare.json b/save/contexts/cuttlefish/saturn-purebare.json
new file mode 100644
index 0000000..f9ffddf
--- /dev/null
+++ b/save/contexts/cuttlefish/saturn-purebare.json
@@ -0,0 +1,117 @@
+{
+  "interpreterName": "cuttlefish",
+  "interpreterVersion": "v0.1",
+  "hunks": [
+    {
+      "type": "manager",
+      "name": "nrol",
+      "inputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray",
+          "connections": [
+            {
+              "inHunkIndex": "1",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "view",
+      "name": "tlview",
+      "inputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "msgs",
+          "type": "byteArray",
+          "connections": [
+            {
+              "inHunkIndex": "0",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "adhoc/saturn",
+      "name": "adhoc/saturn_2",
+      "inputs": [
+        {
+          "name": "posn",
+          "type": "array"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "outx",
+          "type": "number"
+        },
+        {
+          "name": "outy",
+          "type": "number"
+        },
+        {
+          "name": "outz",
+          "type": "number"
+        },
+        {
+          "name": "posn",
+          "type": "array",
+          "connections": [
+            {
+              "inHunkIndex": "4",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "adhoc/tpath",
+      "name": "adhoc/tpath_3",
+      "outputs": [
+        {
+          "name": "position",
+          "type": "array",
+          "connections": [
+            {
+              "inHunkIndex": "2",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ],
+      "states": [
+        {
+          "name": "reset",
+          "type": "boolean",
+          "value": "false"
+        }
+      ]
+    },
+    {
+      "type": "interface/threejs_ghost",
+      "name": "interface/threejs_ghost_9",
+      "inputs": [
+        {
+          "name": "point",
+          "type": "array"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
-- 
GitLab