2

So, I have an array like this:

    var my_array = [
     '00000000000000000',
     '00000111111110000',
     '00000111111110000',
     '00000111111110000',
     '00000111111110000',
     '00000111111110000',
     '00000000000000000'
    ]

...and I'd like to get a function that is able to rotate the array (2d matrix above) by a certain angle (e.g 30°) around a certain point (x/y center of array : e.g X: 8, Y: 3).

So the result for 30° should maybe look like this: (Array is not that exact, just an example...)

var rotated_array = [
  "00000000000000000",
  "00000000001100000",
  "00000000111110000",
  "00000001111111000",
  "00000111111111100",
  "00000111111111000",
  "00000011111100000",
  "00000001110000000",
  "00000000100000000",
  "00000000000000000"
]

I've already created a function you can find below, but the function has some errors (The rotated matrix is missing some points and looks kind of destroyed --> You can test it on your own below).

I hope somebody can help me fixing my code, so however...

Thanks in advance, jonas.


BTW: I have marked all 'new' points which were never used with a '*'-character, afterwards I will use zeros instead!

var my_array = [
  '00000000000000000000000',
  '00000000000000000000000',
  '00000000000000000000000',
  '00000000000000000000000',
  '00000011111111000000000',
  '00000011111111000000000',
  '00000011111111000000000',
  '00000011111111000000000',
  '00000011111111000000000',
  '00000000000000000000000',
  '00000000000000000000000',
  '00000000000000000000000',
  '00000000000000000000000'
]

Array.prototype.rotate_matrix = function(angle, cx, cy) {
  function generate_matrix(rows,cols,value){
    var arr = [];
    for (var i=0; i < rows; i++) {
        arr.push([]);arr[i].push(new Array(cols));
        for (var j=0; j < cols; j++) arr[i][j] = value;
    }; return arr;
  }
  var radians = (Math.PI / 180) * angle;
  var array = generate_matrix(this.length, this[0].length, '*')
  for (var i=0; i<this.length; i++) {
    for (var j=0; j<this[i].length;j++) {
      var character = this[i][j],
      cos = Math.cos(radians),
      sin = Math.sin(radians),
      newx = Math.round((cos * (j - cx)) + (sin * (i - cy)) + cx) < this[i].length ? Math.round((cos * (j - cx)) + (sin * (i - cy)) + cx) : -1,
      newy = Math.round((cos * (i - cy)) - (sin * (j - cx)) + cy) < this[i].length ? Math.round((cos * (i - cy)) - (sin * (j - cx)) + cy) : 1;
      try {array[newy][newx]=character;}
      catch(e) {
        array[i][j] = character
      }
    }
  }
  array = array.map(a => [a.join('')])
  return array.concat.apply([],array);
}


console.log(my_array.rotate_matrix(30,(my_array[0].length/2),(my_array.length/2)))
Jonas0000
  • 1,085
  • 1
  • 12
  • 36
  • Hey @Piterden, 2-3 hours sounds like a long time period. If it's too long for you, you do not have to help me, I'm not asking you to spend half the day doing my (kind of stupid) task. But of course I would still be happy about solutions... Haha Greeting, jonas :) – Jonas0000 Nov 18 '17 at 09:18
  • It is not stupid! Very interesting, but not simple task. I will try when I would have some more free time. – Piterden Nov 18 '17 at 09:20
  • Ok, of course, you're right @Piterden... the task is absolutely not that simple. However, sound good, thanks a lot in advance :) – Jonas0000 Nov 18 '17 at 09:22
  • I wrote the Rectangle class ) – Piterden Nov 18 '17 at 09:45
  • I can not get your comment @Piterden. Do you mean you're done? Or do you mean something completely different?? :p – Jonas0000 Nov 18 '17 at 09:51
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/159281/discussion-between-piterden-and-jonas0000). – Piterden Nov 18 '17 at 09:57
  • https://codepen.io/denis_efremov/pen/OOzNoY – Piterden Nov 18 '17 at 11:03
  • Your rectangle class looks good and is working fine, but I would be interested in how much the class helps you to rotate the matrix? :) – Jonas0000 Nov 18 '17 at 11:20
  • I sure, these classes are necessary for it – Piterden Nov 18 '17 at 12:36
  • Sound legit @Piterden – Jonas0000 Nov 18 '17 at 12:40
  • Possible duplicate of [How can I rotate a 2d array by LESS than 90°, to the best approximation?](https://stackoverflow.com/questions/40584764/how-can-i-rotate-a-2d-array-by-less-than-90-to-the-best-approximation) – Spektre Nov 18 '17 at 16:43
  • see related or duplicates: https://stackoverflow.com/a/40585975/2521214 and https://stackoverflow.com/a/40355825/2521214 and https://stackoverflow.com/a/29741248/2521214 and https://stackoverflow.com/a/44299929/2521214 The idea is to 1. loop through target image pixels instead of source that will remove the holes. 2. use nearest neighbor or bilinear filtering to compensate not exact coordinate match. – Spektre Nov 18 '17 at 16:50
  • @Spektre Ok. I can not get your thoughts at all. Maybe you can provide some code snippets to help me :) Thanks a lot in advance, jonas – Jonas0000 Nov 18 '17 at 17:13
  • @Jonas0000 not in javascript As I am more C++ oriented but in the QAs I linked you will find examples of rotating matrices and images this way. – Spektre Nov 18 '17 at 18:24
  • 1
    A rotation by 30° will not map integer coordinates to integer coordinates. So be precise whether you (a) want each 1 in the input mapped to an approximate output position (would leave gaps in output and / or other coordinates covered multiple times), or (b) want to map each output position to its approximate input position and copy the value from there (a bit like raytracing), or (c) want to infer the outline and transform that (i.e. talk about rotated rectangles and pixels inside or outside of these), or (d) interpolate (would lead to fractional values between 0 and 1). – MvG Nov 19 '17 at 13:04
  • Exactly if you check the links I commented before their cover this (each differently) Either you truncate (will create holes or slight shape distortion as it is not 1:1 mapping) or interpolate (will change the numbers from `1` to `<=1`) or you use only 90deg rotation (or 45/90 for ASCII) So which is it ? – Spektre Sep 30 '18 at 08:21

0 Answers0