Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions lib/mx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/* Jake & Bobby Pearse 2018.

j.t.pearse@gmail.com

Using a string of lights as a 2d Array

A single strip can be treated as a serpentine array.

We can treat a single strip of lights as a serpentine array by correcting the address of pixels on odd numbered columns

Regular 2d array serpentine array

|0|5|10| |0|9|10|
|1|6|11| |1|8|11|
|2|7|12| Need to |2|7|12|
|3|8|13| === correct odd ===> |3|6|13|
|4|9|14| numbered columns |4|5|14|

NOTE: if for some mad reason you want to start with pixel 0 at the bottom, you should reverse EVEN numbered rows :)

As we can see in a sane world, column 1 is reversed. As are all odd-numbered columns.
address will calculate the corrected value for pixels.

examples
========

get a corrected pixel number
============================

const NUM_ROWS = 5

address(6,NUM_ROWS)
=> 8


light up all pixels on row 1 of strip
=====================================

for (const p = 0; p < strip.length; p++){
if (rowNum(p,NUM_ROWS) === 1){
strip.pixel(address(p,ROW_NUM)).color('white')
}
}

*/
const abs = Math.abs
const floor = Math.floor

// return the uncorrected row number of pixel p
const rowNum = (p, rows) => p % rows

// return the uncorrected column number of pixel p
const columnNum = (p, rows) => floor(p/rows)

// find the corrected pixel number at the top of a reversed column
const rowZeroVal = (p,rows) => {

const columnHalf = floor(columnNum(p,rows)/2)+1
const doubleRows = rows * 2
return (columnHalf * doubleRows) - 1
}

// pixel p is in an odd numbered column => true || false
const columnIsOdd = (p, rows) => columnNum(p, rows) % 2 > 0

//corrected value of pixel p, for odd numbered columns
const address = (p, rows) => {

if (columnIsOdd(p, rows)) {
return p + abs( p - rowZeroVal(p,rows)) - rowNum(p,rows)
}
return p
}


// check if a pixel is inside a bounding rectangle
function inRange(p,first,last,rows){
return (
rowNum(p,rows) >= rowNum(first,rows) &&
rowNum(p,rows) <= rowNum(last,rows) &&
columnNum(p,rows) >= columnNum(first,rows) &&
columnNum(p,rows) <= columnNum(last,rows)
)
}

// reduce a 2d array with a bounding rectangle
const rectRange = (first, last, rows, pixelArray) => pixelArray.filter(p => inRange(p, first, last, rows))

module.exports = {
address,
columnNum,
rowZeroVal,
columnIsOdd,
rowNum,
inRange,
rectRange
}
38 changes: 38 additions & 0 deletions test/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ var sinon = require("sinon");
var five = require("johnny-five");
var pixel = require("../lib/pixel.js");

var mx = require("../lib/mx");

var Board = five.Board;

function newBoard() {
Expand Down Expand Up @@ -360,3 +362,39 @@ exports["Pixel"] = {
test.done();
},
};
exports["mx"] = {
rowNum : function(test) {
test.equals(3,mx.rowNum(13,5),"In a grid with 5 rows, pixel 13 is in row 3");
test.done();
},
colNum : function(test) {
test.equals(2,mx.columnNum(13,5), "in a grid with 5 rows, pixel 13 is in column 2");
test.done();
},
rowZeroVal : function(test) {
// pixel 5 will be in column 1
test.equals(9, mx.rowZeroVal(5,5), "in a grid with 5 rows pixel 9 is at the top of column 1");
test.done();
},
columnIsOdd : function(test) {
test.equals(true,mx.columnIsOdd(5,5),"in a grid with 5 rows, pixel five is in an odd-numbered column");
test.equals(false,mx.columnIsOdd(11,5), "in a grid with 5 rows, pixel 11 is not in an odd-numbered column");
test.done();
},
address: function(test) {
test.equals(9,mx.address(5,5),"in a grid with 5 rows pixel 5 should map to pixel 9");
test.equals(4,mx.address(4,5),"in a grid with 5 rows pixel 4 should not be altered")
test.done();
},
inRange: function(test) {
test.equals(true,mx.inRange(8,2,13,5),"in a grid of 5 rows pixel 8 is in the range of 2,13");
test.equals(false,mx.inRange(6,2,13,5),"in a grid of 5 rows pixel 6 is not in range 2,13");
test.done();
},
rectRange : function(test){
const grid = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]
const rec = [2,3,7,8,12,13];
test.deepEqual(rec,mx.rectRange(2,13,5,grid),"in a grid of 5 rows return all pixel values which lie inside a rectangle bounded by 2 and 13")
test.done();
}
};