Mapping Complex Objects

AHH Thank you for the shove back to 2D land and all of your help ! :wink: I found an error in my transform - I was mangling some of the coordinates, But better now.

Dropped the z element - its a bit easier to visualize flipping around just X and Y.

The -Y trick worked in combination with rotating the display 180 degrees.

But was still not able to do it in software mapping alone, without also rotating the display yet. Tried -y, -x, -x-y but -y is the closest.

In any-case, the published map is not correct.

The map from Jason’s site , in the mapper tab the radius of the spirals expand /increase and flow ‘counter clockwise’ but doing an index walk i see they are wired up flowing ‘clockwise’.

but between the map hack and the rotating the display upside down its good.

thanks again!!

1 Like

I made a static pattern that just shows 3 static lines for mapping, red for x axis, green for y, and blue for z. The lines look fine on the first half but pixels look mismapped on the second half.

Full mask:

First half correct:

second half looks wrong:

These are both the same panel with the same map so not sure how they would end up differently.

Here’s the pattern code:

export function render3D(index, x, y, z) {
if(x < .55 && x > .45) {
    hsv(1, 1, 1)
} else if (y < .55 && y > .45) { // y
    hsv(.3, 1, 1)
} else if(z < .5 && z > .4) { // z
    hsv(.7, 1, 1)
} else {
hsv(0,0,0)
}
}

And here’s the map, pretty much same as above before

function (pixelCount) {
var map = []
var zend = 0
var xoffset = 0
var offset = false
var angleOffset = 0
var cone = 0
var isFirst = true

// map F64
zend = -60
if(offset) {xoffset = -5}
angleOffset = 4 //###########################
cone = 1
var pixelsPerFibonacciDisc = 128
buildFermatSpiral(xoffset,0,.10,pixelsPerFibonacciDisc,map,zend,angleOffset,cone,isFirst)

// map helix connecting
var helixCount = (pixelCount-(pixelsPerFibonacciDisc*2));
zend = 20
angleOffset = 3 //###########################
count = helixCount/2
zend = buildHelixMap(helixCount, map,zend,angleOffset,count, pixelsPerFibonacciDisc)

zend = zend + 10
angleOffset = 1.8 //###########################
zend = buildHelixMap(helixCount, map,zend,angleOffset,count, pixelsPerFibonacciDisc)

// map F64
if(offset) {xoffset = 5}
angleoffset = 2.5 //###########################
cone = -1
isFirst = false
buildFermatSpiral(xoffset,0,.10,pixelsPerFibonacciDisc,map,zend+60,angleoffset,cone,isFirst)

// fake extra pixels added to map to set the bounds of the
// coordinate space so the normalizer preserves aspect ratio
var scale = 2;
if(offset) {scale = 6}
map.push([-scale,-scale, -60])
map.push([scale,scale, zend+120])

var OffPixel = pixelCount - pixelsPerFibonacciDisc
Px = map[OffPixel][0] + 0
Py = map[OffPixel][1] -1
Pz = map[OffPixel][2] + 60
map[OffPixel] = [Px,Py,Pz]

return map;
}

function buildFermatSpiral(originX, originY, spacing, pixelCount,map, zend, angleOffset, cone, isFirst) {

reallocation = [0, 13, 26, 39, 52, 65, 78, 91, 104, 117, 122, 109, 96, 83, 70, 57, 44, 31, 18, 5, 10, 23, 36, 49, 62, 75, 88, 101, 114, 127, 119, 106, 93, 80, 67, 54, 41, 28, 15, 2, 7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 116, 103, 90, 77, 64, 51, 38, 25, 12, 4, 17, 30, 43, 56, 69, 82, 95, 108, 121, 126, 113, 100, 87, 74, 61, 48, 35, 22, 9, 1, 14, 27, 40, 53, 66, 79, 92, 105, 118, 123, 110, 97, 84, 71, 58, 45, 32, 19, 6, 11, 24, 37, 50, 63, 76, 89, 102, 115, 120, 107, 94, 81, 68, 55, 42, 29, 16, 3, 8, 21, 34, 47, 60, 73, 86, 99, 112, 125]

for (var i = 0; i < pixelCount; i++) {
r = spacing * Math.sqrt(reallocation[i]);
theta = reallocation[i] * 2.3998277 + angleOffset // golden angle
if(isFirst) {
y = originY + (r * Math.sin(theta));
} else {
y = originY - (r * Math.sin(theta));
}

x = originX + (r * Math.cos(theta));
map.push([x, y, (cone*r*r*50)+zend])    
}
}

function buildHelixMap(pixelCount,map,zend,angleOffset,count, pixelsPerFibonacciDisc) {
var loops = 12

var helixCount = (pixelCount-(pixelsPerFibonacciDisc*2));
var rowCount = helixCount/35;
var lastZ = 0;

for (i = 0; i < count; i++) {
c = i / pixelCount * Math.PI * 2 * loops
c = c + angleOffset
lastZ = (i/rowCount) + zend;
map.push([Math.cos©, Math.sin©, lastZ])
}

return lastZ;
}

That panel isn’t aligned right so the spots are the wrong places. I suspect the entire disc needs a slightly angle change (in the map)

that was my first thought too, so I unglued it and rotated into the same orientation as the other panel, fixed the angle offset, and no change. it rotated but still more blurry.
I tried multiple different angle offsets on the second panel hoping one would magically align. I spent more time than I’d like to admit cracking this theoretical safe and it was the same all around. if there’s some perfect 10-decimal precision offset where the stars align I haven’t found it yet.

Oooh… I know what it is… It’s MIRRORed.

The orientation is reversed from the other.

I missed that in the mapping we did. Sorry.

Imagine them stacked on top of each other, one is spinning one way and the other is back to back with it and spinning the other way. Fixable in the map, just make the direction of the calculation reversed (so clockwise versus counterclockwise)

I understand what you’re saying in theory, at least I thought I did until I went to the mapper tab
not sure how to reverse the spin direction though

So just as we did “IsFirst” to change direction (the Y), you need to also change one from the other, so it spins in the opposite direction. You might also need to change the X, I haven’t run the numbers. Basically you want it to be the opposite of the first (imagine it mirrored) but only in one axis (Y I believe). Try making theta negative in the Y first. At worst, you’ll need to modify the if and add the X into it as well.

This was my solution for the EvilGenius Fibonocci displays. Using the math is better in theory … BUT across the different sizes of 32, 64 Mini, 64Micro, (mini and micro are close or the same) , 128, and the 256 dont work great with the math. Various pixels need correcting and or just a deviation between the actual wiring and the math. The math is close but not as good as the original published data transformed.

I ended up with something like this for now…

function (pixelCount) {

var map = [];
  
//EvilGenius Fibonocci  Map data notes.
//flip means the input/DIN is oriented at the BOTTOM rather than the top. 
// upside down physical orientation and the NEGATIVE -y values fix the mirrored XYA map.
FIPI_64_XYA = "140,128,0|189,114,249|208,91,241|214,63,232|208,34,223|146,0,200|168,21,208|180,48,217|180,76,226|162,106,235|152,78,212|146,47,203|129,25,194|103,11,185|72,5,176|40,38,162|70,35,171|97,42,180|120,61,188|131,101,197|107,87,174|79,69,165|50,68,156|23,78,147|0,98,139|7,143,124|23,118,133|46,102,142|76,98,151|93,122,136|57,131,128|37,152,119|28,179,110|29,209,101|87,255,78|68,230,86|59,202,95|62,174,104|80,148,113|113,142,99|91,181,90|94,210,81|109,235,72|133,252,63|202,235,40|172,234,49|145,224,58|125,203,67|117,170,75|145,183,52|170,201,43|198,205,34|227,198,25|253,181,17|255,134,2|235,157,11|210,171,20|181,173,29|148,153,38|175,145,14|207,138,6|228,120,255|240,93,246|244,63,237"
FIPI_64_XY_flip = "140,-128|189,-114|208,-91|214,-63|208,-34|146,-0|168,-21|180,-48|180,-76|162,-106|152,-78|146,-47|129,-25|103,-11|72,-5|40,-38|70,-35|97,-42|120,-61|131,-101|107,-87|79,-69|50,-68|23,-78|0,-98|7,-143|23,-118|46,-102|76,-98|93,-122|57,-131|37,-152|28,-179|29,-209|87,-255|68,-230|59,-202|62,-174|80,-148|113,-142|91,-181|94,-210|109,-235|133,-252|202,-235|172,-234|145,-224|125,-203|117,-170|145,-183|170,-201|198,-205|227,-198|253,-181|255,-134|235,-157|210,-171|181,-173|148,-153|175,-145|207,-138|228,-120|240,-93|244,-63"
FIPI_128_XYA = "137,130,128|170,121,247|182,105,239|186,86,230|182,66,221|172,47,212|156,31,203|135,19,194|110,13,186|83,13,177|26,55,154|49,39,163|74,30,171|99,28,180|121,33,189|141,43,198|155,57,207|164,75,216|164,95,224|151,115,233|145,96,210|141,75,201|129,60,192|112,50,184|91,46,175|69,49,166|47,59,157|27,74,148|11,96,139|0,122,131|9,166,116|11,139,125|19,114,134|33,93,143|50,78,152|70,69,160|90,67,169|108,72,178|123,85,187|130,112,196|114,102,173|96,90,164|77,89,155|58,96,146|43,110,137|32,129,129|25,152,120|25,177,111|32,203,102|45,227,93|85,247,79|65,228,88|51,207,97|43,184,105|42,161,114|47,140,123|58,123,132|74,112,141|94,109,150|105,126,135|81,132,126|68,146,118|62,165,109|63,185,100|70,206,91|84,225,82|103,240,73|127,251,65|154,255,56|218,224,33|193,235,42|167,240,50|142,237,59|119,229,68|101,216,77|89,199,86|83,181,95|84,161,103|96,143,112|118,139,98|104,166,89|106,186,80|116,202,71|132,215,63|152,221,54|175,222,45|198,216,36|221,204,27|241,185,18|255,115,252|248,142,4|236,166,13|219,184,22|199,197,31|178,203,39|158,202,48|140,195,57|126,181,66|121,158,75|140,167,52|157,180,43|176,182,34|195,178,25|213,166,16|227,148,8|237,126,255|241,101,246|239,74,237|193,21,214|210,42,223|221,66,232|225,91,241|222,114,250|214,134,2|201,150,11|184,159,20|164,160,29|142,147,37|160,141,14|181,137,5|196,124,253|204,106,244|206,85,235|202,63,226|191,42,218|174,24,209|152,9,200|125,0,191"
FIPI_128_XY_flip = "137,-130|170,-121|182,-105|186,-86|182,-66|172,-47|156,-31|135,-19|110,-13|83,-13|26,-55|49,-39|74,-30|99,-28|121,-33|141,-43|155,-57|164,-75|164,-95|151,-115|145,-96|141,-75|129,-60|112,-50|91,-46|69,-49|47,-59|27,-74|11,-96|0,-122|9,-166|11,-139|19,-114|33,-93|50,-78|70,-69|90,-67|108,-72|123,-85|130,-112|114,-102|96,-90|77,-89|58,-96|43,-110|32,-129|25,-152|25,-177|32,-203|45,-227|85,-247|65,-228|51,-207|43,-184|42,-161|47,-140|58,-123|74,-112|94,-109|105,-126|81,-132|68,-146|62,-165|63,-185|70,-206|84,-225|103,-240|127,-251|154,-255|218,-224|193,-235|167,-240|142,-237|119,-229|101,-216|89,-199|83,-181|84,-161|96,-143|118,-139|104,-166|106,-186|116,-202|132,-215|152,-221|175,-222|198,-216|221,-204|241,-185|255,-115|248,-142|236,-166|219,-184|199,-197|178,-203|158,-202|140,-195|126,-181|121,-158|140,-167|157,-180|176,-182|195,-178|213,-166|227,-148|237,-126|241,-101|239,-74|193,-21|210,-42|221,-66|225,-91|222,-114|214,-134|201,-150|184,-159|164,-160|142,-147|160,-141|181,-137|196,-124|204,-106|206,-85|202,-63|191,-42|174,-24|152,-9|125,0"
FIPI_256_XYA = "133,126,0|156,120,247|165,109,238|168,96,229|165,82,220|158,69,211|147,57,203|132,49,194|114,45,185|95,45,176|76,50,167|57,59,159|41,74,150|28,92,141|19,114,132|15,138,123|17,163,115|24,188,106|37,211,97|56,231,88|123,255,65|96,248,74|73,235,83|53,218,92|38,198,100|28,175,109|24,152,118|25,129,127|31,107,136|41,89,144|55,74,153|71,63,162|89,57,171|106,56,180|122,59,188|136,66,197|146,76,206|152,88,215|152,102,224|143,116,232|138,103,209|136,88,201|128,77,192|115,71,183|101,68,174|85,70,165|70,77,157|56,88,148|44,103,139|37,121,130|33,141,121|34,163,113|41,184,104|53,205,95|69,222,86|90,236,77|114,245,69|140,249,60|167,247,51|226,208,28|204,224,37|180,235,46|154,241,54|129,240,63|106,234,72|85,223,81|67,209,90|54,191,98|46,172,107|43,152,116|44,132,125|50,115,134|60,101,142|72,90,151|86,84,160|100,82,169|113,86,178|123,95,186|128,114,195|117,107,172|104,98,163|90,98,155|78,103,146|67,112,137|59,126,128|54,142,119|54,159,111|59,177,102|68,195,93|82,210,84|100,222,75|121,230,67|143,233,58|167,230,49|191,223,40|212,209,31|231,191,23|246,168,14|255,142,5|251,98,246|251,125,255|245,151,8|233,174,17|218,194,26|199,209,35|178,219,44|156,223,52|134,223,61|114,218,70|96,208,79|82,195,88|73,180,96|67,164,105|66,148,114|70,134,123|78,122,132|89,114,140|103,112,149|111,123,135|94,128,126|84,138,117|80,151,108|81,165,100|86,180,91|96,193,82|109,203,73|126,211,64|145,214,56|165,212,47|185,206,38|204,194,29|220,178,20|233,158,12|241,134,3|244,109,250|241,83,241|232,58,232|217,35,223|179,11,209|201,28,218|217,48,227|229,71,235|235,95,244|235,120,253|230,142,6|220,163,15|207,179,24|190,192,33|172,200,41|154,203,50|136,202,59|121,196,68|108,187,77|99,175,85|95,162,94|96,148,103|104,136,112|120,133,98|110,152,89|111,166,80|118,177,71|130,186,62|144,190,54|160,191,45|176,187,36|192,178,27|206,165,18|217,148,10|224,128,1|227,107,247|224,84,239|216,62,230|202,41,221|184,24,212|162,11,203|137,2,195|110,0,186|44,28,163|68,16,172|94,9,180|120,8,189|145,13,198|168,23,207|187,37,216|202,55,224|212,75,233|216,96,242|216,116,251|212,135,4|203,151,13|191,164,22|177,173,31|162,177,39|148,177,48|135,172,57|126,162,66|122,146,75|136,153,52|147,161,43|161,163,34|174,160,25|186,152,16|197,139,8|204,124,254|206,106,245|205,87,237|198,69,228|187,51,219|172,36,210|152,25,201|130,18,193|106,16,184|81,20,175|58,29,166|36,44,157|17,64,149|0,133,126|5,106,134|15,81,143|30,60,152|49,44,161|71,32,170|93,26,178|116,25,187|138,29,196|157,38,205|173,50,214|185,65,222|192,82,231|195,99,240|193,115,249|187,129,2|178,140,11|166,147,20|152,148,28|137,138,37|149,134,14|164,131,5|175,122,252|180,110,243|182,95,235|179,80,226|171,65,217|159,52,208|143,42,199|125,36,191|105,34,182|83,37,173|63,45,164|44,59,155|28,77,147|16,98,138|9,123,129|7,149,120|12,176,111|23,202,103"
FIPI_256_XY_flip = "133,-126|156,-120|165,-109|168,-96|165,-82|158,-69|147,-57|132,-49|114,-45|95,-45|76,-50|57,-59|41,-74|28,-92|19,-114|15,-138|17,-163|24,-188|37,-211|56,-231|123,-255|96,-248|73,-235|53,-218|38,-198|28,-175|24,-152|25,-129|31,-107|41,-89|55,-74|71,-63|89,-57|106,-56|122,-59|136,-66|146,-76|152,-88|152,-102|143,-116|138,-103|136,-88|128,-77|115,-71|101,-68|85,-70|70,-77|56,-88|44,-103|37,-121|33,-141|34,-163|41,-184|53,-205|69,-222|90,-236|114,-245|140,-249|167,-247|226,-208|204,-224|180,-235|154,-241|129,-240|106,-234|85,-223|67,-209|54,-191|46,-172|43,-152|44,-132|50,-115|60,-101|72,-90|86,-84|100,-82|113,-86|123,-95|128,-114|117,-107|104,-98|90,-98|78,-103|67,-112|59,-126|54,-142|54,-159|59,-177|68,-195|82,-210|100,-222|121,-230|143,-233|167,-230|191,-223|212,-209|231,-191|246,-168|255,-142|251,-98|251,-125|245,-151|233,-174|218,-194|199,-209|178,-219|156,-223|134,-223|114,-218|96,-208|82,-195|73,-180|67,-164|66,-148|70,-134|78,-122|89,-114|103,-112|111,-123|94,-128|84,-138|80,-151|81,-165|86,-180|96,-193|109,-203|126,-211|145,-214|165,-212|185,-206|204,-194|220,-178|233,-158|241,-134|244,-109|241,-83|232,-58|217,-35|179,-11|201,-28|217,-48|229,-71|235,-95|235,-120|230,-142|220,-163|207,-179|190,-192|172,-200|154,-203|136,-202|121,-196|108,-187|99,-175|95,-162|96,-148|104,-136|120,-133|110,-152|111,-166|118,-177|130,-186|144,-190|160,-191|176,-187|192,-178|206,-165|217,-148|224,-128|227,-107|224,-84|216,-62|202,-41|184,-24|162,-11|137,-2|110,0|44,-28|68,-16|94,-9|120,-8|145,-13|168,-23|187,-37|202,-55|212,-75|216,-96|216,-116|212,-135|203,-151|191,-164|177,-173|162,-177|148,-177|135,-172|126,-162|122,-146|136,-153|147,-161|161,-163|174,-160|186,-152|197,-139|204,-124|206,-106|205,-87|198,-69|187,-51|172,-36|152,-25|130,-18|106,-16|81,-20|58,-29|36,-44|17,-64|0,-133|5,-106|15,-81|30,-60|49,-44|71,-32|93,-26|116,-25|138,-29|157,-38|173,-50|185,-65|192,-82|195,-99|193,-115|187,-129|178,-140|166,-147|152,-148|137,-138|149,-134|164,-131|175,-122|180,-110|182,-95|179,-80|171,-65|159,-52|143,-42|125,-36|105,-34|83,-37|63,-45|44,-59|28,-77|16,-98|9,-123|7,-149|12,-176|23,-202"
  
//assumes only 1 display connected, and selects the map based on the pixel count. 
switch(pixelCount) {
  case 256:
    map = map.concat(stringTo2dArray(FIPI_256_XY_flip, "|", ","));
    break;
  case 128:
    map = map.concat(stringTo2dArray(FIPI_128_XY_flip, "|", ","));
    break;
  default:
    map = map.concat(stringTo2dArray(FIPI_64_XY_flip, "|", ","));
} 

  return map

}

// string to split d1 = element delimiter, d2=index delimiter 
function stringTo2dArray(string, d1, d2) {return string.split(d1).map(function(x){return x.split(d2)});}
3 Likes

and here is the map data for the FIbonocci 32:

FIPI_32Mini_XY = “281,204|234,125|239,72|329,50|292,88|277,150|327,123|372,90|443,144|387,141|325,181|375,190|433,202|472,235|433,285|396,239|353,257|382,305|385,363|324,360|335,299|297,256|280,331|239,364|156,319|206,320|260,285|206,267|154,261|138,173|172,211|243,227|217,182|181,135”

1 Like


Got it working sharp now

3 Likes

I had to move the first item of the reallocation array to the end for some reason.

        if(isFirst) {
      reallocation = [0, 13, 26, ... 99, 112, 125]
    } else {
      reallocation = [13, 26, 39, ... 112, 125,0]
    }

still don’t really understand what I did wrong before, but it’s working. Thanks everyone who helped me out on this project!

3 Likes

@Sunandmooncouture ,
Awesome! It’s been really exciting to see what you’ve built here, and all the challenges you’ve overcome.

You have a sensor board in there too, yeah? I was inspired, and though it would be really cool to see something that kept the pattern oriented like Glow Flow, so I ported it to the new transform API, along with a simpler example that has waves going up.

Check out “Upward waves 3D using accelerometer” and “GlowFlow (3D coord transform API port)” on the pattern site.

Original Glow Flow here:

3 Likes

Thanks @wizard !
It’s been challenging but thankfully the community is very helpful.
Yes I have a sensor board inside, and loaded all the sound patterns.

I wanted to add accelerometer data to matrix rain and doom fire but haven’t tried it yet and matrix rain didn’t render properly on my setup.
I’ll def check out those patterns and report back!

I’m glad you got it working, but I don’t quite know why shifting the first pixel on that disc to the end of the list worked. Anyone got an idea? (@JasonCoon @wizard ?)

An off by one error perhaps? Intuitively, I would think that for identical panels, the first and last would be the same.

But, if swapping them just happened to shift one of the arrays forward by one pixel that happens to correct a previous off by one error, and we don’t notice that the last pixel isn’t getting data (or getting the wrong data, but I’d think the off by one would mean there’s 1 more physical LED than pixel count & map size).

1 Like

Agreed, typical fence post problem. probably one of my maths forgot to use zero based index arrays. I remember at one point I had to manually fix one pixel in the map, and I think it was the first one on the left panel. I should probably do a formal code review and dig up the issue but I’m in a rush to get these shipped out in time for EDC and it looks good now so I’m just gonna send it

1 Like

I think you nailed it, it’s got one less real pixel than the map has(non disc), so that second disc first “zeroth” pixel is already given a position on the map, and we don’t see that, because the wrong positions of the rest are more visible (and now corrected, look right).

So remove one pixel from the rings, and restore the pixel in the disc. If you count the ring pixels, I’m sure your actual count is one less than you have in the map.

the pixelCount I figured by trial and error. On any pixelBlaze, if you set the pixelCount to fewer than the physical leds, then the next led not included turns on full brightness. No idea why it does this other than it helps with this process so I assumed that’s how everyone does it. So anyways you gradually increase the pixel count until that one full brightness pixel drops off the edge of the strip.

I think the problem is in my maths here. This calculates how many pixels are in each half of the helix.

var numHelixes = 2
var helixCount = (pixelCount-(pixelsPerFibonacciDisc*2))/numHelixes

When I wrote this, I had an even number of pixels. I lost a pixel off one helix in the great war of the soldering of 30AWG ribbon cables. so now pixelCount is an odd number.
helixCount comes back as 205.5 and I should have one helix count 205 and one 206?
that should also fix the one pixel I had to manually remap.
There’s also a bunch of unused variables and scoping issues, bad var names etc. so def need to do some code cleanup

2 Likes

A post was split to a new topic: How do I map LEDs

A post was merged into an existing topic: How do I map LEDs