Maroula Bacharidou

MAS.863 | How to Make (Almost) Anything


Interface and application programming

*
1. Assignment
2. Idea: from pins to shapes
3. Steps
*

Representing the interaction of multiple processesors / from pins to shapes

1. Assignment

This week's assignment was to write an application that interfaces with an input &/or output device that we made, comparing as many tool options as possible. This week was one of the hardest and most challenging as I got to know a lot of new things - I had an experience in application design but this assignment was different because it involved input and output devices in the design of the application. I completed this assignment after the networking and communications week and while working for my final project, as I wanted to make the interface work with the boards I designed for my final project and their networking system.

Figure 1. An application understanding connections and sending signals.
2. Idea: from pins to shapes

The idea for this application is to get inputs through serial communication about the connections between different pins of the processors, which are connected to sides A, B, C and D of rectangular shapes, and then produce images on the screen of te computer; these images represent the configurations between the shapes. The user of the interface can also control an RGB LED that is placed on each processor.

3. Steps

The application works as follows:
- a node.js application generates an array of .svg drawings of 3-d rectangles
- the user runs a script that gets inputs about the connection between different pins- that are assigned to different "sides" of the rectangles
- the user loads an html page that executes the javascript code and generates the .svg image - this image represents the connections between different pins of the boards that are currently connected.

Below is the code that generates the .svg images:

var path, group;
var angle = 0, Y = 0;
var angleT = Math.PI/9, YT = 50;
var Explode = 1;
var cubes = [];
var autorefresh = false;
var palette = [ "rgba(255,255,255,0.7)", "rgba(200,200,255,0.7)", "rgba(255,200,200,0.7)", "rgba(200,255,200,0.7)"];

function _rotate( array , times ){
  while( times-- ){
    var temp = array.shift();
    array.push( temp )
  }
}
function _test() {
  var A = [
    [-1,-1,-1,-1,-1,-1],
    [-1,-1,-1,-1,-1,-1],
    [-1,-1,-1,-1,-1,-1],
    [-1,-1,-1,-1,-1,-1],
    [-1,-1,-1,-1,-1,-1],
    [-1,-1,-1,-1,-1,-1],
  ];
  for(var i=0;i<10;i++) {
    while(1) {
      var x = Math.ceil( Math.random() * 4 );
      var y = Math.ceil( Math.random() * 4 );
      if(A[x][y]==-1) {
        A[x][y] = i;
        break;
      }
    }
  }
  var msg = [];
  for(var i in A) {
    for(var j in A[i]) {
      if(A[i][j] < 0) continue;
      var n = [ A[i-1][j],A[i][j*1+1],A[i*1+1][j],A[i][j-1] ];
      for(var k=0;k<n.length;k++) if(n[k]<0) n[k] = A[i][j];
      rotate(n, Math.floor( Math.random() ) );
      msg[A[i][j] ] = n.join('');
    }
  }
  return msg.join('|');
}

function reconstruct(data) {
  data = data.replace(/[^\x20-\x7E]+/g, '').split('|');
  for(var i in data) data[i] = data[i].split('');
  for(var i in cubes) cubes[i].active = 0;
  var dy = [1,0,-1,0];
  var dx = [0,1,0,-1];
  function dfs(node,x,y) {
    cubes[node].active = 1;
    cubes[node].x = x;
    cubes[node].y = y;
    
    for(var i in data[node]) {
      var nei = data[node][i];
      if(cubes[nei].active) continue;
      if(nei == node) continue;
      var times = 10;
      while( data[nei][(i*1+2)%4] != node && times-- ){
        var temp = data[nei].shift();
        data[nei].push( temp );
      }
      if(times < 0) {
        console.log("error");
        continue;
      }
      dfs( nei, x+dx[i], y+dy[i] );
    }
  }
  
  dfs(0, 0, 0);
  for(var i in cubes) if(!cubes[i].active) cubes[i].color = 0;
}



$(function(){
  path = $('path').first().clone();  
  group = $('g').first().clone();
  var socket = io(":8080");
  socket.on('message', function (data) {
    //console.log( data.trim() );
    reconstruct( data.trim() );
    
    render();
  });
  
  function refresh() {
    socket.emit('refresh');
    //reconstruct( test() );
  
    //render();
  }
  
  var mouse;
  $("svg").mousedown(function(e) {mouse = {x:e.clientX,y:e.clientY};});
  $("svg").mousemove(function(e) {
    if(!mouse) return;
  
    var dx = e.clientX - mouse.x
    var dy = e.clientY - mouse.y;
    mouse = {x:e.clientX,y:e.clientY};
  
    angle += dx / 150; Y += dy/5;
    if(Y > YT) Y = YT;
    if(Y < -YT) Y = -YT;
    if(angle > angleT) angle = angleT;
    if(angle < -angleT) angle = -angleT;
    render();  
  });
  $("svg").mouseup(function() {mouse = false;});
  //$("svg").mouseout(function() {mouse = false;});
  
  $("svg").on("click","g",function() {
    var id = $(this).attr("id").split("-")[1] | 0;
    cubes[id].color = (cubes[id].color + 1)%palette.length;
    socket.emit('led', {state: cubes[id].color, id: id});
    render();
  });
  $("#refresh").click(refresh);
  $("#autorefresh").change(function() {
    if(autorefresh) {
      clearInterval(autorefresh);
      autorefresh = false;return;
    }
    autorefresh = setInterval(refresh, 1000);
  });
  $("#explode").click(function() {
    Explode = Math.round(Explode);
    $({_:Explode}).animate({_:3-Explode}, {
        duration: 200,
        step: function(val) {
          Explode = val;
          render();
        }
    })
  });
  
  //for(var x=-2;x<=2;x++)
  //for(var y=-2;y<=2;y++) {
  for(var i=0;i<10;i++) {
    cubes.push({x:i,y:0,color:0,active:1});
  } 
  render();
});

function P(x,y,z) {
  var D1 = 200;
  var D2 = 200;
  var nx = Math.cos( angle )*x - Math.sin( angle )*z;
  var ny = y + Y;
  var nz = Math.sin( angle )*x + Math.cos( angle )*z;
  return [ D1 * nx / (D2 + nz), D1 * ny / (D2 + nz), nz ];
}

function add(p,clss,level) {
  pth.attr('d',p);
  return pth;
}

function drawPolygon(poly) {
  var p = "M" + poly[ poly.length - 1 ].join();
  for(var point of poly) p += " " + point.join();
  return p + "z";
}


function fix(root) {
  var elems = root.children().get();
  elems.sort(function(a,b) {
    return $(b).data('z') - $(a).data('z');
  });
  $.each(elems, function(idx, itm) { root.append(itm); });
}

function drawCube(id,x,y,z,color) {
  var r = 10, d = 2*r;
  x = x*d; y = -y*d; z = z*d;
  var s = [0,12,6,15,12,6];
  var g = group.clone();
  for(var i=0;i<6;i++) {
    var mx = s[i];
    var my = s[(i+1)%6];
    var mz = s[(i+2)%6];
    
    var a = [], zindex = 0, xindex = 0, yindex = 0;
    for(var j=0;j<4;j++) {
      var pnt = P(x+(mx%2?-r:r),y+(my%2?-r:r),z+(mz%2?-r:r));
      zindex += pnt.pop();
      xindex += pnt[0];
      yindex += pnt[1];
      a.push( pnt );
      mx >>= 1; my >>= 1; mz >>= 1;
    }
    
    var p = path.clone();
    p.attr('d',drawPolygon(a));
    p.data('z',Math.abs(xindex) + Math.abs(yindex) + 15*zindex);
    g.append(p);
  }
  var p = P(x,y,z);
  var p2 = P(x,y,z+r);
  g.attr("id",id);
  g.css("fill", palette[ color ]);
  g.data('z',Math.abs(p2[0]-p[0]) + Math.abs(p2[1] - p[1]) );
  $('svg').append(g);
  fix(g);
}

function render() {
  $('svg').html('');
  for(var i=0;i<cubes.length;i++) {
    if(cubes[i].active)
    drawCube("cube-"+i,cubes[i].x*Explode,cubes[i].y*Explode,0,cubes[i].color);
  }
  fix( $('svg') );
}



This was an exercise that took longer than I expected, and it can be considered as a large part of my final project.