From 6797f3c6ccfeeb5ca18ef8ed327da4bd89dfed2a Mon Sep 17 00:00:00 2001
From: Jake Read <jake.read@cba.mit.edu>
Date: Tue, 19 Nov 2019 19:43:50 -0500
Subject: [PATCH] cleanup systems, simplify context / system distinction
 (oboy),

---
 hunks/image/distanceTransform.js              | 269 +++++------
 hunks/image/thresholdrgba.js                  |  29 --
 hunks/image/vectorize.js                      | 427 +++++++++---------
 .../dbg-l0-oneStepperUsb.json                 |   0
 save/{systems => old-systems}/dbg-l0.json     |   0
 .../dbg-l1-3added.json                        |   0
 .../dbg-l1-aReady.json                        |   0
 .../dbg-l1-aSaturn.json                       |   0
 .../dbg-l1-ab_ready.json                      |   0
 .../dbg-l1-ab_tpath.json                      |   0
 .../dbg-l1-abcReady.json                      |   0
 .../dbg-l1-abc_msegs.json                     |   0
 .../dbg-l1-abc_tpath.json                     |   0
 .../dbg-lowerLevel.json                       |   0
 .../dbg-pipe-ghost.json                       |   0
 .../dbg-pipe-nolog.json                       |   0
 save/{systems => old-systems}/dbg-pipe.json   |   0
 .../demo-system-jog-a.json                    |   0
 save/{systems => old-systems}/fft.json        |   0
 .../{systems => old-systems}/lr-l1-abdef.json |   0
 .../lr-l1-abdef_prep.json                     |   0
 .../lr-l1-abdef_refreshed.json                |   0
 .../lr-l1-abdef_rf_dmseg.json                 |   0
 .../lr-l1-abdef_rf_enable.json                |   0
 .../{systems => old-systems}/lr-l1_abdef.json |   0
 .../lr-l1_abdef_saturn-jog.json               |   0
 .../lr-l1_saturn-jog.json                     |   0
 save/systems/png-to-vectors.json              | 259 +++++++++++
 typeset.js                                    |   3 +
 view/vcontextmenu.js                          |   8 +-
 30 files changed, 618 insertions(+), 377 deletions(-)
 rename save/{systems => old-systems}/dbg-l0-oneStepperUsb.json (100%)
 rename save/{systems => old-systems}/dbg-l0.json (100%)
 rename save/{systems => old-systems}/dbg-l1-3added.json (100%)
 rename save/{systems => old-systems}/dbg-l1-aReady.json (100%)
 rename save/{systems => old-systems}/dbg-l1-aSaturn.json (100%)
 rename save/{systems => old-systems}/dbg-l1-ab_ready.json (100%)
 rename save/{systems => old-systems}/dbg-l1-ab_tpath.json (100%)
 rename save/{systems => old-systems}/dbg-l1-abcReady.json (100%)
 rename save/{systems => old-systems}/dbg-l1-abc_msegs.json (100%)
 rename save/{systems => old-systems}/dbg-l1-abc_tpath.json (100%)
 rename save/{systems => old-systems}/dbg-lowerLevel.json (100%)
 rename save/{systems => old-systems}/dbg-pipe-ghost.json (100%)
 rename save/{systems => old-systems}/dbg-pipe-nolog.json (100%)
 rename save/{systems => old-systems}/dbg-pipe.json (100%)
 rename save/{systems => old-systems}/demo-system-jog-a.json (100%)
 rename save/{systems => old-systems}/fft.json (100%)
 rename save/{systems => old-systems}/lr-l1-abdef.json (100%)
 rename save/{systems => old-systems}/lr-l1-abdef_prep.json (100%)
 rename save/{systems => old-systems}/lr-l1-abdef_refreshed.json (100%)
 rename save/{systems => old-systems}/lr-l1-abdef_rf_dmseg.json (100%)
 rename save/{systems => old-systems}/lr-l1-abdef_rf_enable.json (100%)
 rename save/{systems => old-systems}/lr-l1_abdef.json (100%)
 rename save/{systems => old-systems}/lr-l1_abdef_saturn-jog.json (100%)
 rename save/{systems => old-systems}/lr-l1_saturn-jog.json (100%)
 create mode 100644 save/systems/png-to-vectors.json

diff --git a/hunks/image/distanceTransform.js b/hunks/image/distanceTransform.js
index 3667a50..51f7004 100644
--- a/hunks/image/distanceTransform.js
+++ b/hunks/image/distanceTransform.js
@@ -1,7 +1,7 @@
 /*
 hunks/image/distanceTransform.js
 
-find distance to nearest pixel 
+find distance to nearest pixel
 
 Jake Read at the Center for Bits and Atoms with Neil Gershenfeld and Leo McElroy
 (c) Massachusetts Institute of Technology 2019
@@ -48,137 +48,140 @@ export default function distanceTransform() {
   let height = new Output("number", "height", this);
   this.outputs.push(height);
 
-  // Helper Functions
-
-  // view
-  // this.dom = {}
-  this.init = () => {
-    //this.dom = $('<div>').get(0)
-  };
-
-  /*
-    this.onload = () => {}
-    */
-
-  //loop
-  this.loop = () => {
-    if (imageIn.io() && !imageOut.io() && !width.io() && !height.io()) {
-      let image = imageIn.get();
-      console.log("image2", image)
-
-      function work() {
-        self.onmessage = function(e) {
-          const distanceTransformHelper = imageRGBA => {
-            // const ny = imageRGBA.height;
-            // const nx = imageRGBA.width;
-            // var input = new Uint8ClampedArray(imageRGBA.buffer)
-            // var output = new Float32Array(nx*ny)
-
-            //helpers
-            // const distance = (g, x, y, i) => (y-i)*(y-i) + g[i][x]*g[i][x];
-            //
-            // const intersection = (g, x, y0, y1) => (g[y0][x]*g[y0][x] - g[y1][x]*g[y1][x] + y0*y0 - y1*y1)/(2.0*(y0-y1));
-
-            var ny = imageRGBA.height;
-            var nx = imageRGBA.width;
-            var input = imageRGBA.data;
-            var output = new Float32Array(nx * ny);
-            function distance(g, x, y, i) {
-              return (y - i) * (y - i) + g[i][x] * g[i][x];
-            }
-            function intersection(g, x, y0, y1) {
-              return (
-                (g[y0][x] * g[y0][x] -
-                  g[y1][x] * g[y1][x] +
-                  y0 * y0 -
-                  y1 * y1) /
-                (2.0 * (y0 - y1))
-              );
+  // yonder worker f'n
+  function work() {
+    self.onmessage = function(e) {
+      const distanceTransformHelper = imageRGBA => {
+        // const ny = imageRGBA.height;
+        // const nx = imageRGBA.width;
+        // var input = new Uint8ClampedArray(imageRGBA.buffer)
+        // var output = new Float32Array(nx*ny)
+
+        //helpers
+        // const distance = (g, x, y, i) => (y-i)*(y-i) + g[i][x]*g[i][x];
+        //
+        // const intersection = (g, x, y0, y1) => (g[y0][x]*g[y0][x] - g[y1][x]*g[y1][x] + y0*y0 - y1*y1)/(2.0*(y0-y1));
+
+        var ny = imageRGBA.height;
+        var nx = imageRGBA.width;
+        var input = imageRGBA.data;
+        var output = new Float32Array(nx * ny);
+
+        function distance(g, x, y, i) {
+          return (y - i) * (y - i) + g[i][x] * g[i][x];
+        }
+
+        function intersection(g, x, y0, y1) {
+          return (
+            (g[y0][x] * g[y0][x] -
+              g[y1][x] * g[y1][x] +
+              y0 * y0 -
+              y1 * y1) /
+            (2.0 * (y0 - y1))
+          );
+        }
+        //
+        // allocate arrays
+        //
+        var g = [];
+        for (var y = 0; y < ny; ++y) g[y] = new Uint32Array(nx);
+        var h = [];
+        for (var y = 0; y < ny; ++y) h[y] = new Uint32Array(nx);
+        var distances = [];
+        for (var y = 0; y < ny; ++y) distances[y] = new Uint32Array(nx);
+        var starts = new Uint32Array(ny);
+        var minimums = new Uint32Array(ny);
+        var d;
+        //
+        // column scan
+        //
+        for (var y = 0; y < ny; ++y) {
+          //
+          // right pass
+          //
+          var closest = -nx;
+          for (var x = 0; x < nx; ++x) {
+            if (input[(ny - 1 - y) * nx * 4 + x * 4 + 0] != 0) {
+              g[y][x] = 0;
+              closest = x;
+            } else g[y][x] = x - closest;
+          }
+          //
+          // left pass
+          //
+          closest = 2 * nx;
+          for (var x = nx - 1; x >= 0; --x) {
+            if (input[(ny - 1 - y) * nx * 4 + x * 4 + 0] != 0) closest = x;
+            else {
+              d = closest - x;
+              if (d < g[y][x]) g[y][x] = d;
             }
-            //
-            // allocate arrays
-            //
-            var g = [];
-            for (var y = 0; y < ny; ++y) g[y] = new Uint32Array(nx);
-            var h = [];
-            for (var y = 0; y < ny; ++y) h[y] = new Uint32Array(nx);
-            var distances = [];
-            for (var y = 0; y < ny; ++y) distances[y] = new Uint32Array(nx);
-            var starts = new Uint32Array(ny);
-            var minimums = new Uint32Array(ny);
-            var d;
-            //
-            // column scan
-            //
-            for (var y = 0; y < ny; ++y) {
-              //
-              // right pass
-              //
-              var closest = -nx;
-              for (var x = 0; x < nx; ++x) {
-                if (input[(ny - 1 - y) * nx * 4 + x * 4 + 0] != 0) {
-                  g[y][x] = 0;
-                  closest = x;
-                } else g[y][x] = x - closest;
-              }
-              //
-              // left pass
-              //
-              closest = 2 * nx;
-              for (var x = nx - 1; x >= 0; --x) {
-                if (input[(ny - 1 - y) * nx * 4 + x * 4 + 0] != 0) closest = x;
-                else {
-                  d = closest - x;
-                  if (d < g[y][x]) g[y][x] = d;
-                }
-              }
-            }
-            //
-            // row scan
-            //
-            for (var x = 0; x < nx; ++x) {
-              var segment = 0;
-              starts[0] = 0;
-              minimums[0] = 0;
-              //
-              // down
-              //
-              for (var y = 1; y < ny; ++y) {
-                while (
-                  segment >= 0 &&
-                  distance(g, x, starts[segment], minimums[segment]) >
-                    distance(g, x, starts[segment], y)
-                )
-                  segment -= 1;
-                if (segment < 0) {
-                  segment = 0;
-                  minimums[0] = y;
-                } else {
-                  var newstart = 1 + intersection(g, x, minimums[segment], y);
-                  if (newstart < ny) {
-                    segment += 1;
-                    minimums[segment] = y;
-                    starts[segment] = newstart;
-                  }
-                }
-              }
-              //
-              // up
-              //
-              for (var y = ny - 1; y >= 0; --y) {
-                d = Math.sqrt(distance(g, x, y, minimums[segment]));
-                output[(ny - 1 - y) * nx + x] = d;
-                if (y == starts[segment]) segment -= 1;
+          }
+        }
+        //
+        // row scan
+        //
+        for (var x = 0; x < nx; ++x) {
+          var segment = 0;
+          starts[0] = 0;
+          minimums[0] = 0;
+          //
+          // down
+          //
+          for (var y = 1; y < ny; ++y) {
+            while (
+              segment >= 0 &&
+              distance(g, x, starts[segment], minimums[segment]) >
+              distance(g, x, starts[segment], y)
+            )
+              segment -= 1;
+            if (segment < 0) {
+              segment = 0;
+              minimums[0] = y;
+            } else {
+              var newstart = 1 + intersection(g, x, minimums[segment], y);
+              if (newstart < ny) {
+                segment += 1;
+                minimums[segment] = y;
+                starts[segment] = newstart;
               }
             }
+          }
+          //
+          // up
+          //
+          for (var y = ny - 1; y >= 0; --y) {
+            d = Math.sqrt(distance(g, x, y, minimums[segment]));
+            output[(ny - 1 - y) * nx + x] = d;
+            if (y == starts[segment]) segment -= 1;
+          }
+        }
+
+        return output;
+      };
+
+      const newOut = distanceTransformHelper(e.data);
+      self.postMessage(newOut);
+    };
+  }
 
-            return output;
-          };
+  let stash = {}
+  let haveData = false
+  let working = false
 
-          const newOut = distanceTransformHelper(e.data);
-          self.postMessage(newOut);
-        };
-      }
+  //loop
+  this.loop = () => {
+    // if we have previously completed work, and clear outputs, ship 'em
+    if(haveData && !imageOut.io() && !width.io() && !height.io()){
+      imageOut.put(stash.data)
+      width.put(stash.inputImage.width)
+      height.put(stash.inputImage.height)
+      haveData = false
+    }
+    // if we donot have previously completed work (i.e. a clear stash)
+    // and work todo, do it
+    if (imageIn.io() && !working && !haveData) {
+      stash.inputImage = imageIn.get()
 
       var blob = new Blob(["(" + work.toString() + "())"]);
       var url = window.URL.createObjectURL(blob);
@@ -186,15 +189,15 @@ export default function distanceTransform() {
 
       worker.onmessage = e => {
         const message = e.data;
-        imageOut.put(message);
-        console.log("image", image)
-
-        width.put(image.width);
-        height.put(image.height);
+        stash.data = e.data
         worker.terminate();
+        working = false
+        haveData = true 
       };
 
-      worker.postMessage(image);
+      // this assumes succes, but OK
+      working = true
+      worker.postMessage(stash.inputImage);
     }
   };
 }
diff --git a/hunks/image/thresholdrgba.js b/hunks/image/thresholdrgba.js
index a20923a..4b92afb 100644
--- a/hunks/image/thresholdrgba.js
+++ b/hunks/image/thresholdrgba.js
@@ -46,7 +46,6 @@ export default function Threshold() {
 
   // Helper Functions
   const thresholdRGBA = (imageRGBA, threshold) => {
-    console.log(imageRGBA);
     const w = imageRGBA.width;
     const h = imageRGBA.height;
     const buf = imageRGBA.data;
@@ -82,34 +81,6 @@ export default function Threshold() {
     return imgdata;
   };
 
-  // view
-  // this.dom = {}
-  this.init = () => {
-    //this.dom = $('<div>').get(0)
-  };
-
-  /*
-  this.onload = () => {
-    // kind of don't really need to show this - we can pull a 'display' unit off of whichever line we
-    // would like, including this one ...
-    const target = $('<div>').get(0);
-    $(this.dom).append(target);
-
-    const view = html `
-    <button
-      @mousedown=${() => {
-        // console.log("imageIn", imageIn.get());
-        // console.log("copied", deepCopy(imageIn));
-        const newOut = thresholdRGBA(imageIn.get(), threshold.value)
-        imageOut.put(newOut);
-      }}>
-      Calculate
-    </button>
-    `
-    render(view, target);
-  }
-  */
-
   //loop
   this.loop = () => {
     if (imageIn.io() && !imageOut.io()) {
diff --git a/hunks/image/vectorize.js b/hunks/image/vectorize.js
index f92e510..abf29c3 100644
--- a/hunks/image/vectorize.js
+++ b/hunks/image/vectorize.js
@@ -1,7 +1,7 @@
 /*
 hunks/image/vectorize.js
 
-write vectors from distance field 
+write vectors from distance field
 
 Jake Read at the Center for Bits and Atoms with Neil Gershenfeld and Leo McElroy
 (c) Massachusetts Institute of Technology 2019
@@ -37,238 +37,239 @@ export default function Vectorize() {
   let vectors = new Output("array", "Vectors", this);
   this.outputs.push(vectors);
 
-  // Helper Functions
-
-  // view
-  // this.dom = {}
-  this.init = () => {
-    //this.dom = $('<div>').get(0)
-  };
-
-  /*
-    this.onload = () => {}
-    */
-
-  //loop
-  this.loop = () => {
-    if (imageIn.io() && !vectors.io()) {
-      function work() {
-        self.onmessage = function(e) {
-          const vectorizeHelper = (imageRGBA, vectorFit = 1, sort = true) => {
-            var h = imageRGBA.height;
-            var w = imageRGBA.width;
-            var input = imageRGBA.data;
-            var northsouth = 0;
-            var north = 128;
-            var south = 64;
-            var eastwest = 1;
-            var east = 128;
-            var west = 64;
-            var startstop = 2;
-            var start = 128;
-            var stop = 64;
-            var path = [];
-            //
-            // edge follower
-            //
-            function follow_edges(row, col) {
+  function work() {
+    self.onmessage = function(e) {
+      const vectorizeHelper = (imageRGBA, vectorFit = 1, sort = true) => {
+        var h = imageRGBA.height;
+        var w = imageRGBA.width;
+        var input = imageRGBA.data;
+        var northsouth = 0;
+        var north = 128;
+        var south = 64;
+        var eastwest = 1;
+        var east = 128;
+        var west = 64;
+        var startstop = 2;
+        var start = 128;
+        var stop = 64;
+        var path = [];
+        //
+        // edge follower
+        //
+        function follow_edges(row, col) {
+          if (
+            input[(h - 1 - row) * w * 4 + col * 4 + northsouth] != 0 ||
+            input[(h - 1 - row) * w * 4 + col * 4 + eastwest] != 0
+          ) {
+            path[path.length] = [
+              [col, row]
+            ];
+            while (1) {
               if (
-                input[(h - 1 - row) * w * 4 + col * 4 + northsouth] != 0 ||
-                input[(h - 1 - row) * w * 4 + col * 4 + eastwest] != 0
+                input[(h - 1 - row) * w * 4 + col * 4 + northsouth] & north
+              ) {
+                input[(h - 1 - row) * w * 4 + col * 4 + northsouth] =
+                  input[(h - 1 - row) * w * 4 + col * 4 + northsouth] &
+                  ~north;
+                row += 1;
+                path[path.length - 1][path[path.length - 1].length] = [
+                  col,
+                  row
+                ];
+              } else if (
+                input[(h - 1 - row) * w * 4 + col * 4 + northsouth] & south
+              ) {
+                input[(h - 1 - row) * w * 4 + col * 4 + northsouth] =
+                  input[(h - 1 - row) * w * 4 + col * 4 + northsouth] &
+                  ~south;
+                row -= 1;
+                path[path.length - 1][path[path.length - 1].length] = [
+                  col,
+                  row
+                ];
+              } else if (
+                input[(h - 1 - row) * w * 4 + col * 4 + eastwest] & east
               ) {
-                path[path.length] = [[col, row]];
-                while (1) {
-                  if (
-                    input[(h - 1 - row) * w * 4 + col * 4 + northsouth] & north
-                  ) {
-                    input[(h - 1 - row) * w * 4 + col * 4 + northsouth] =
-                      input[(h - 1 - row) * w * 4 + col * 4 + northsouth] &
-                      ~north;
-                    row += 1;
-                    path[path.length - 1][path[path.length - 1].length] = [
-                      col,
-                      row
-                    ];
-                  } else if (
-                    input[(h - 1 - row) * w * 4 + col * 4 + northsouth] & south
-                  ) {
-                    input[(h - 1 - row) * w * 4 + col * 4 + northsouth] =
-                      input[(h - 1 - row) * w * 4 + col * 4 + northsouth] &
-                      ~south;
-                    row -= 1;
-                    path[path.length - 1][path[path.length - 1].length] = [
-                      col,
-                      row
-                    ];
-                  } else if (
-                    input[(h - 1 - row) * w * 4 + col * 4 + eastwest] & east
-                  ) {
-                    input[(h - 1 - row) * w * 4 + col * 4 + eastwest] =
-                      input[(h - 1 - row) * w * 4 + col * 4 + eastwest] & ~east;
-                    col += 1;
-                    path[path.length - 1][path[path.length - 1].length] = [
-                      col,
-                      row
-                    ];
-                  } else if (
-                    input[(h - 1 - row) * w * 4 + col * 4 + eastwest] & west
-                  ) {
-                    input[(h - 1 - row) * w * 4 + col * 4 + eastwest] =
-                      input[(h - 1 - row) * w * 4 + col * 4 + eastwest] & ~west;
-                    col -= 1;
-                    path[path.length - 1][path[path.length - 1].length] = [
-                      col,
-                      row
-                    ];
-                  } else break;
-                }
+                input[(h - 1 - row) * w * 4 + col * 4 + eastwest] =
+                  input[(h - 1 - row) * w * 4 + col * 4 + eastwest] & ~east;
+                col += 1;
+                path[path.length - 1][path[path.length - 1].length] = [
+                  col,
+                  row
+                ];
+              } else if (
+                input[(h - 1 - row) * w * 4 + col * 4 + eastwest] & west
+              ) {
+                input[(h - 1 - row) * w * 4 + col * 4 + eastwest] =
+                  input[(h - 1 - row) * w * 4 + col * 4 + eastwest] & ~west;
+                col -= 1;
+                path[path.length - 1][path[path.length - 1].length] = [
+                  col,
+                  row
+                ];
+              } else break;
+            }
+          }
+        }
+        //
+        // follow boundary starts
+        //
+        for (var row = 1; row < h - 1; ++row) {
+          col = 0;
+          follow_edges(row, col);
+          col = w - 1;
+          follow_edges(row, col);
+        }
+        for (var col = 1; col < w - 1; ++col) {
+          row = 0;
+          follow_edges(row, col);
+          row = h - 1;
+          follow_edges(row, col);
+        }
+        //
+        // follow interior paths
+        //
+        for (var row = 1; row < h - 1; ++row) {
+          for (var col = 1; col < w - 1; ++col) {
+            follow_edges(row, col);
+          }
+        }
+        //
+        // vectorize path
+        //
+        var error = vectorFit;
+        var vecpath = [];
+        for (var seg = 0; seg < path.length; ++seg) {
+          var x0 = path[seg][0][0];
+          var y0 = path[seg][0][1];
+          vecpath[vecpath.length] = [
+            [x0, y0]
+          ];
+          var xsum = x0;
+          var ysum = y0;
+          var sum = 1;
+          for (var pt = 1; pt < path[seg].length; ++pt) {
+            var xold = x;
+            var yold = y;
+            var x = path[seg][pt][0];
+            var y = path[seg][pt][1];
+            if (sum == 1) {
+              xsum += x;
+              ysum += y;
+              sum += 1;
+            } else {
+              var xmean = xsum / sum;
+              var ymean = ysum / sum;
+              var dx = xmean - x0;
+              var dy = ymean - y0;
+              var d = Math.sqrt(dx * dx + dy * dy);
+              var nx = dy / d;
+              var ny = -dx / d;
+              var l = Math.abs(nx * (x - x0) + ny * (y - y0));
+              if (l < error) {
+                xsum += x;
+                ysum += y;
+                sum += 1;
+              } else {
+                vecpath[vecpath.length - 1][
+                  vecpath[vecpath.length - 1].length
+                ] = [xold, yold];
+                x0 = xold;
+                y0 = yold;
+                xsum = xold;
+                ysum = yold;
+                sum = 1;
               }
             }
-            //
-            // follow boundary starts
-            //
-            for (var row = 1; row < h - 1; ++row) {
-              col = 0;
-              follow_edges(row, col);
-              col = w - 1;
-              follow_edges(row, col);
+            if (pt == path[seg].length - 1) {
+              vecpath[vecpath.length - 1][
+                vecpath[vecpath.length - 1].length
+              ] = [x, y];
             }
-            for (var col = 1; col < w - 1; ++col) {
-              row = 0;
-              follow_edges(row, col);
-              row = h - 1;
-              follow_edges(row, col);
+          }
+        }
+        //
+        // sort path
+        //
+        if (vecpath.length > 1 && sort == true) {
+          var dmin = w * w + h * h;
+          var segmin = null;
+          for (var seg = 0; seg < vecpath.length; ++seg) {
+            var x = vecpath[seg][0][0];
+            var y = vecpath[seg][0][0];
+            var d = x * x + y * y;
+            if (d < dmin) {
+              dmin = d;
+              segmin = seg;
             }
-            //
-            // follow interior paths
-            //
-            for (var row = 1; row < h - 1; ++row) {
-              for (var col = 1; col < w - 1; ++col) {
-                follow_edges(row, col);
+          }
+          if (segmin != null) {
+            var sortpath = [vecpath[segmin]];
+            vecpath.splice(segmin, 1);
+          }
+          while (vecpath.length > 0) {
+            var dmin = w * w + h * h;
+            var x0 =
+              sortpath[sortpath.length - 1][
+                sortpath[sortpath.length - 1].length - 1
+              ][0];
+            var y0 =
+              sortpath[sortpath.length - 1][
+                sortpath[sortpath.length - 1].length - 1
+              ][1];
+            segmin = null;
+            for (var seg = 0; seg < vecpath.length; ++seg) {
+              var x = vecpath[seg][0][0];
+              var y = vecpath[seg][0][1];
+              var d = (x - x0) * (x - x0) + (y - y0) * (y - y0);
+              if (d < dmin) {
+                dmin = d;
+                segmin = seg;
               }
             }
-            //
-            // vectorize path
-            //
-            var error = vectorFit;
-            var vecpath = [];
-            for (var seg = 0; seg < path.length; ++seg) {
-              var x0 = path[seg][0][0];
-              var y0 = path[seg][0][1];
-              vecpath[vecpath.length] = [[x0, y0]];
-              var xsum = x0;
-              var ysum = y0;
-              var sum = 1;
-              for (var pt = 1; pt < path[seg].length; ++pt) {
-                var xold = x;
-                var yold = y;
-                var x = path[seg][pt][0];
-                var y = path[seg][pt][1];
-                if (sum == 1) {
-                  xsum += x;
-                  ysum += y;
-                  sum += 1;
-                } else {
-                  var xmean = xsum / sum;
-                  var ymean = ysum / sum;
-                  var dx = xmean - x0;
-                  var dy = ymean - y0;
-                  var d = Math.sqrt(dx * dx + dy * dy);
-                  var nx = dy / d;
-                  var ny = -dx / d;
-                  var l = Math.abs(nx * (x - x0) + ny * (y - y0));
-                  if (l < error) {
-                    xsum += x;
-                    ysum += y;
-                    sum += 1;
-                  } else {
-                    vecpath[vecpath.length - 1][
-                      vecpath[vecpath.length - 1].length
-                    ] = [xold, yold];
-                    x0 = xold;
-                    y0 = yold;
-                    xsum = xold;
-                    ysum = yold;
-                    sum = 1;
-                  }
-                }
-                if (pt == path[seg].length - 1) {
-                  vecpath[vecpath.length - 1][
-                    vecpath[vecpath.length - 1].length
-                  ] = [x, y];
-                }
-              }
+            if (segmin != null) {
+              sortpath[sortpath.length] = vecpath[segmin];
+              vecpath.splice(segmin, 1);
             }
-            //
-            // sort path
-            //
-            if (vecpath.length > 1 && sort == true) {
-              var dmin = w * w + h * h;
-              var segmin = null;
-              for (var seg = 0; seg < vecpath.length; ++seg) {
-                var x = vecpath[seg][0][0];
-                var y = vecpath[seg][0][0];
-                var d = x * x + y * y;
-                if (d < dmin) {
-                  dmin = d;
-                  segmin = seg;
-                }
-              }
-              if (segmin != null) {
-                var sortpath = [vecpath[segmin]];
-                vecpath.splice(segmin, 1);
-              }
-              while (vecpath.length > 0) {
-                var dmin = w * w + h * h;
-                var x0 =
-                  sortpath[sortpath.length - 1][
-                    sortpath[sortpath.length - 1].length - 1
-                  ][0];
-                var y0 =
-                  sortpath[sortpath.length - 1][
-                    sortpath[sortpath.length - 1].length - 1
-                  ][1];
-                segmin = null;
-                for (var seg = 0; seg < vecpath.length; ++seg) {
-                  var x = vecpath[seg][0][0];
-                  var y = vecpath[seg][0][1];
-                  var d = (x - x0) * (x - x0) + (y - y0) * (y - y0);
-                  if (d < dmin) {
-                    dmin = d;
-                    segmin = seg;
-                  }
-                }
-                if (segmin != null) {
-                  sortpath[sortpath.length] = vecpath[segmin];
-                  vecpath.splice(segmin, 1);
-                }
-              }
-            } else if (
-              (vecpath.length > 1 && sort == false) ||
-              vecpath.length == 1
-            )
-              sortpath = vecpath;
-            else sortpath = [];
+          }
+        } else if (
+          (vecpath.length > 1 && sort == false) ||
+          vecpath.length == 1
+        )
+          sortpath = vecpath;
+        else sortpath = [];
 
-            return sortpath;
-          };
+        return sortpath;
+      };
 
-          const newOut = vectorizeHelper(e.data);
-          self.postMessage(newOut);
-        };
-      }
+      const newOut = vectorizeHelper(e.data);
+      self.postMessage(newOut);
+    };
+  }
 
+  let stash = {}
+  let haveData = false
+  let working = false
+
+  //loop
+  this.loop = () => {
+    if(!vectors.io() && haveData){
+      vectors.put(stash)
+      haveData = false
+    }
+    if (imageIn.io() && !working && !haveData) {
       var blob = new Blob(["(" + work.toString() + "())"]);
       var url = window.URL.createObjectURL(blob);
       var worker = new Worker(url);
 
       worker.onmessage = e => {
-        const message = e.data;
-        console.log(message);
-        vectors.put(message);
+        stash = e.data
+        haveData = true 
         worker.terminate();
+        working = false
       };
 
+      working = true
       worker.postMessage(imageIn.get());
     }
   };
diff --git a/save/systems/dbg-l0-oneStepperUsb.json b/save/old-systems/dbg-l0-oneStepperUsb.json
similarity index 100%
rename from save/systems/dbg-l0-oneStepperUsb.json
rename to save/old-systems/dbg-l0-oneStepperUsb.json
diff --git a/save/systems/dbg-l0.json b/save/old-systems/dbg-l0.json
similarity index 100%
rename from save/systems/dbg-l0.json
rename to save/old-systems/dbg-l0.json
diff --git a/save/systems/dbg-l1-3added.json b/save/old-systems/dbg-l1-3added.json
similarity index 100%
rename from save/systems/dbg-l1-3added.json
rename to save/old-systems/dbg-l1-3added.json
diff --git a/save/systems/dbg-l1-aReady.json b/save/old-systems/dbg-l1-aReady.json
similarity index 100%
rename from save/systems/dbg-l1-aReady.json
rename to save/old-systems/dbg-l1-aReady.json
diff --git a/save/systems/dbg-l1-aSaturn.json b/save/old-systems/dbg-l1-aSaturn.json
similarity index 100%
rename from save/systems/dbg-l1-aSaturn.json
rename to save/old-systems/dbg-l1-aSaturn.json
diff --git a/save/systems/dbg-l1-ab_ready.json b/save/old-systems/dbg-l1-ab_ready.json
similarity index 100%
rename from save/systems/dbg-l1-ab_ready.json
rename to save/old-systems/dbg-l1-ab_ready.json
diff --git a/save/systems/dbg-l1-ab_tpath.json b/save/old-systems/dbg-l1-ab_tpath.json
similarity index 100%
rename from save/systems/dbg-l1-ab_tpath.json
rename to save/old-systems/dbg-l1-ab_tpath.json
diff --git a/save/systems/dbg-l1-abcReady.json b/save/old-systems/dbg-l1-abcReady.json
similarity index 100%
rename from save/systems/dbg-l1-abcReady.json
rename to save/old-systems/dbg-l1-abcReady.json
diff --git a/save/systems/dbg-l1-abc_msegs.json b/save/old-systems/dbg-l1-abc_msegs.json
similarity index 100%
rename from save/systems/dbg-l1-abc_msegs.json
rename to save/old-systems/dbg-l1-abc_msegs.json
diff --git a/save/systems/dbg-l1-abc_tpath.json b/save/old-systems/dbg-l1-abc_tpath.json
similarity index 100%
rename from save/systems/dbg-l1-abc_tpath.json
rename to save/old-systems/dbg-l1-abc_tpath.json
diff --git a/save/systems/dbg-lowerLevel.json b/save/old-systems/dbg-lowerLevel.json
similarity index 100%
rename from save/systems/dbg-lowerLevel.json
rename to save/old-systems/dbg-lowerLevel.json
diff --git a/save/systems/dbg-pipe-ghost.json b/save/old-systems/dbg-pipe-ghost.json
similarity index 100%
rename from save/systems/dbg-pipe-ghost.json
rename to save/old-systems/dbg-pipe-ghost.json
diff --git a/save/systems/dbg-pipe-nolog.json b/save/old-systems/dbg-pipe-nolog.json
similarity index 100%
rename from save/systems/dbg-pipe-nolog.json
rename to save/old-systems/dbg-pipe-nolog.json
diff --git a/save/systems/dbg-pipe.json b/save/old-systems/dbg-pipe.json
similarity index 100%
rename from save/systems/dbg-pipe.json
rename to save/old-systems/dbg-pipe.json
diff --git a/save/systems/demo-system-jog-a.json b/save/old-systems/demo-system-jog-a.json
similarity index 100%
rename from save/systems/demo-system-jog-a.json
rename to save/old-systems/demo-system-jog-a.json
diff --git a/save/systems/fft.json b/save/old-systems/fft.json
similarity index 100%
rename from save/systems/fft.json
rename to save/old-systems/fft.json
diff --git a/save/systems/lr-l1-abdef.json b/save/old-systems/lr-l1-abdef.json
similarity index 100%
rename from save/systems/lr-l1-abdef.json
rename to save/old-systems/lr-l1-abdef.json
diff --git a/save/systems/lr-l1-abdef_prep.json b/save/old-systems/lr-l1-abdef_prep.json
similarity index 100%
rename from save/systems/lr-l1-abdef_prep.json
rename to save/old-systems/lr-l1-abdef_prep.json
diff --git a/save/systems/lr-l1-abdef_refreshed.json b/save/old-systems/lr-l1-abdef_refreshed.json
similarity index 100%
rename from save/systems/lr-l1-abdef_refreshed.json
rename to save/old-systems/lr-l1-abdef_refreshed.json
diff --git a/save/systems/lr-l1-abdef_rf_dmseg.json b/save/old-systems/lr-l1-abdef_rf_dmseg.json
similarity index 100%
rename from save/systems/lr-l1-abdef_rf_dmseg.json
rename to save/old-systems/lr-l1-abdef_rf_dmseg.json
diff --git a/save/systems/lr-l1-abdef_rf_enable.json b/save/old-systems/lr-l1-abdef_rf_enable.json
similarity index 100%
rename from save/systems/lr-l1-abdef_rf_enable.json
rename to save/old-systems/lr-l1-abdef_rf_enable.json
diff --git a/save/systems/lr-l1_abdef.json b/save/old-systems/lr-l1_abdef.json
similarity index 100%
rename from save/systems/lr-l1_abdef.json
rename to save/old-systems/lr-l1_abdef.json
diff --git a/save/systems/lr-l1_abdef_saturn-jog.json b/save/old-systems/lr-l1_abdef_saturn-jog.json
similarity index 100%
rename from save/systems/lr-l1_abdef_saturn-jog.json
rename to save/old-systems/lr-l1_abdef_saturn-jog.json
diff --git a/save/systems/lr-l1_saturn-jog.json b/save/old-systems/lr-l1_saturn-jog.json
similarity index 100%
rename from save/systems/lr-l1_saturn-jog.json
rename to save/old-systems/lr-l1_saturn-jog.json
diff --git a/save/systems/png-to-vectors.json b/save/systems/png-to-vectors.json
new file mode 100644
index 0000000..b2ae0c8
--- /dev/null
+++ b/save/systems/png-to-vectors.json
@@ -0,0 +1,259 @@
+{
+  "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": "image/readPNG",
+      "name": "image/readPNG_2",
+      "outputs": [
+        {
+          "name": "image",
+          "type": "ImageData",
+          "connections": [
+            {
+              "inHunkIndex": "3",
+              "inHunkInput": "0"
+            }
+          ]
+        },
+        {
+          "name": "dpi",
+          "type": "number"
+        }
+      ],
+      "states": [
+        {
+          "name": "release",
+          "type": "boolean",
+          "value": "false"
+        }
+      ]
+    },
+    {
+      "type": "image/thresholdRGBA",
+      "name": "image/thresholdRGBA_3",
+      "inputs": [
+        {
+          "name": "image",
+          "type": "ImageData"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "image",
+          "type": "ImageData",
+          "connections": [
+            {
+              "inHunkIndex": "4",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ],
+      "states": [
+        {
+          "name": "threshold",
+          "type": "number",
+          "value": "0.5"
+        }
+      ]
+    },
+    {
+      "type": "image/distanceTransform",
+      "name": "image/distanceTransform_4",
+      "inputs": [
+        {
+          "name": "image",
+          "type": "ImageData"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "image",
+          "type": "Float32Array",
+          "connections": [
+            {
+              "inHunkIndex": "5",
+              "inHunkInput": "0"
+            }
+          ]
+        },
+        {
+          "name": "width",
+          "type": "number",
+          "connections": [
+            {
+              "inHunkIndex": "5",
+              "inHunkInput": "1"
+            }
+          ]
+        },
+        {
+          "name": "height",
+          "type": "number",
+          "connections": [
+            {
+              "inHunkIndex": "5",
+              "inHunkInput": "2"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "image/offset",
+      "name": "image/offset_5",
+      "inputs": [
+        {
+          "name": "image",
+          "type": "Float32Array"
+        },
+        {
+          "name": "width",
+          "type": "number"
+        },
+        {
+          "name": "height",
+          "type": "number"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "image",
+          "type": "ImageData",
+          "connections": [
+            {
+              "inHunkIndex": "6",
+              "inHunkInput": "0"
+            },
+            {
+              "inHunkIndex": "9",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ],
+      "states": [
+        {
+          "name": "offset",
+          "type": "number",
+          "value": "4"
+        }
+      ]
+    },
+    {
+      "type": "image/edgeDetect",
+      "name": "image/edgeDetect_7",
+      "inputs": [
+        {
+          "name": "image",
+          "type": "ImageData"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "image",
+          "type": "ImageData",
+          "connections": [
+            {
+              "inHunkIndex": "7",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "image/orientEdges",
+      "name": "image/orientEdges_9",
+      "inputs": [
+        {
+          "name": "image",
+          "type": "ImageData"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "image",
+          "type": "ImageData",
+          "connections": [
+            {
+              "inHunkIndex": "8",
+              "inHunkInput": "0"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "image/vectorize",
+      "name": "image/vectorize_10",
+      "inputs": [
+        {
+          "name": "image",
+          "type": "ImageData"
+        }
+      ],
+      "outputs": [
+        {
+          "name": "Vectors",
+          "type": "array"
+        }
+      ]
+    },
+    {
+      "type": "image/displayImageData",
+      "name": "image/displayImageData_9",
+      "inputs": [
+        {
+          "name": "image",
+          "type": "ImageData"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/typeset.js b/typeset.js
index 6d1b999..516a48e 100644
--- a/typeset.js
+++ b/typeset.js
@@ -134,6 +134,9 @@ const TSET = [
         } else {
           return 0
         }
+      },
+      reference: function(bool){
+        return bool 
       }
     }
   }, { // booleanArray: 33,
diff --git a/view/vcontextmenu.js b/view/vcontextmenu.js
index 34b4d6e..18cefc8 100644
--- a/view/vcontextmenu.js
+++ b/view/vcontextmenu.js
@@ -240,6 +240,7 @@ function cfContextMenu(evt, view, dt) {
   })
 
   // save patches
+  /*
   addContextOption('<i class="em em-blue_book"></i> save this context', (ce) => {
     let ptch = scope.patchset.writeCurrent()
     setupForSave(ce, (name) => {
@@ -253,7 +254,9 @@ function cfContextMenu(evt, view, dt) {
       }, 'json')
     })
   })
+  */
 
+  /*
   // load patches,
   addContextOption('<i class="em em-hammer"></i> restore into this context', (ce) => {
     $(ce.target).closest('li').append(' > loading a list ...')
@@ -281,6 +284,7 @@ function cfContextMenu(evt, view, dt) {
       }
     })
   })
+  */
 
   /* ---------------------------    ---------------------------- */
   /* ------------------ QUEEN OF THE MOUNTAIN ------------------ */
@@ -289,7 +293,7 @@ function cfContextMenu(evt, view, dt) {
   // write these if the click was into the toplevel
   if (scope.name !== 'tlview') return false
   // save the entire system,
-  addContextOption('<i class="em em-books"></i> save this entire system', (ce) => {
+  addContextOption('<i class="em em-books"></i> save this system', (ce) => {
     // for posterity, bc of often-broken-due-to-def-rewrite (bugfarm!),
     // we run a GO before we do this...
     let debug = true
@@ -358,7 +362,7 @@ function cfContextMenu(evt, view, dt) {
 
   // MERGE A SYSTEM
   // careful: two 'ce' variables in lower scope ?
-  addContextOption('<i class="em em-hammer_and_wrench"></i> restore an entire system', (ce) => {
+  addContextOption('<i class="em em-hammer_and_wrench"></i> restore a system', (ce) => {
     // get the data ...
     view.patchset.findSystems().then((list) => {
       // title, and options
-- 
GitLab