How can I rotate object in pixel grid properly? - javascript

I have an 2D grid made from 1D array with with and height property. In that grid I have a box object which I want to rotate by X amount of degrees.
I have used this formula to rotate each pixel of object in grid:
newX = floor(cos(angle)*x - sin(angle)*y)
newY = floor(sin(angle)*x + cos(angle)*y)
It works fine when the box is small but if the box is bigger I get some empty cells. How can I fill empty spaces witch should be filled.
Here is an example of box with width and height 10 and then rotated by 45 degrees:

Perform reverse mapping:
Walk through all pixels of result. You can use bounding box of rotated image and scan its lines.
For every pixel one get coordinates of corresponding source pixel. If they lie in valid range (source rectangle), then copy source color to result.
To get reverse mapping formula, just change angle sign (if you have pure rotation without shift)
oldx = cos(angle)*newx + sin(angle)*newy
oldy = -sin(angle)*newx + cos(angle)*newy

Related

Calculate width of hexagons in a field

I am drawing a hexagonal grid using javascript and svg. The grid needs to have a fixed width (let's say, of 1000px). The dimensions of the grid can differ, but I have that information (the columns and rows). I have written a function that given a hexagons 'bounding box' width (the height is a factor 0.8660254 of the width), will calculate all 6 points and draw a polygon between them. I am staggering the x coordinate such that the polygons neatly connect.
However, the part I am stuck on currently is: How do I figure out the width of the polygons such that they take up the most available space on the canvas? I cannot simply do width of the canvas / number of columns because that doesn't take into account the staggering (see the image below)
How can I figure out how to stretch the hexagons such that they all fit and take up as much space as they can?
If you have C columns and hexagon side size (unknown yet) is x, we can write inequality:
x/2 + C*x*3/2 <= width
x*(1+3*C)>=2*width
x <= 2*width / (1+3*C)
So calculate the right part and get floored integer (if you need integer side)
For height with R rows:
x*sqrt(3)/2 + R*x*sqrt(3)/2 <= height
x <= 2*height / (sqrt(3) + R*sqrt(3))
Get min value from calculated sizes to fit both width and height
You need some trigonometry
Each Hexigon neighbor is at an increment of 60 degrees (pi/3) angle. Use cos (pi/3) * radius for the x location adjustment, and +/- sin (pi/3) * radius for height adjustment.

How are the bounds calculated in the Leaflet CRS.Simple tutorial?

In the example in Leaflet (for non geographic image), they set "bounds". I am trying to understand how they computed the values
var bounds = [[-26.5,-25], [1021.5,1023]];
The origin is bottom-left and y increases upwards / x towards the right. How did negative numbers turn up here? Also, after experimentation, I see that the actual pixel coordinates change if you specify different coordinates for bounds. I have a custom png map which I would like to use but I am unable to proceed due to this.
Oh, you mean this image:
If you open the full file (available at https://github.com/Leaflet/Leaflet/blob/v1.4.0/docs/examples/crs-simple/uqm_map_full.png ) with an image editor, you'll see that it measures 2315x2315 pixels. Now, the pixel that represents the (0,0) coordinate is not at a corner of the image, but rather 56 pixels away from the lower-left corner of the image:
Similarly, the (1000, 1000) coordinate is about 48 pixels from the top-right corner of the image:
Therefore, if we measure pixel coordinates of the grid corners:
Game coordinate (0, 0) → Pixel coordinate (59, 56)
Game coordinate (1000, 1000) → Pixel coordinate (2264, 2267)
The problem here is finding the bounds (measured in game coordinates) of the image. Or, in other words:
Pixel coordinate (0, 0) → Game coordinate (?, ?)
Pixel coordinate (2315, 2315) → Game coordinate (?, ?)
We know that the pixel-to-game-coordinate ratio is constant, we know the image size and the distance to the coordinates grid, so we can infer stuff:
1000 horizontal game units = image width - left margin - right margin
or
1000 horizontal game units = 2315px - 56px - 48px = 2213px
therefore the pixel/game unit ratio is
2213px / 1000 game units = 2.213 px/unit
therefore the left margin is...
~59px = ~59px / (2.213px/unit) ~= 26.66 game units
...therefore the left edge of the image is at ~ -26.66 game units. Idem for the right margin...
~51px = ~51px / (2.213px/unit) = ~23.04 game units
...therefore the right edge of the image is at ~1023.04 game units
Repeating that for the top and bottom margins we can fill up all the numbers:
Pixel coordinate (0, 0) → Game coordinate (-26.66, -25)
Pixel coordinate (2315, 2315) → Game coordinate (1023.04, 1025)
Why don't these numbers match the ones in the example exactly? Because I might have used a different pixel for measurement when I wrote that Leaflet tutorial. Still, the error is negligible.
Let me remark a sentence from that tutorial:
One common mistake when using CRS.Simple is assuming that the map units equal image pixels. In this case, the map covers 1000x1000 units, but the image is 2315x2315 pixels big. Different cases will call for one pixel = one map unit, or 64 pixels = one map unit, or anything. Think in map units in a grid, and then add your layers (L.ImageOverlays, L.Markers and so on) accordingly.
If you have your own game map (or anything else), you should ask yourself: Where is the (0,0) coordinate? What are the coordinates of the image edges in the units I'm gonna use?

How to rotate image - canvas pixel manipulation?

I use getImageData and putImageData to draw on canvas from a buffer canvas. I use these methods because I have a large number of particles and these proved to provide the best performance.
Now I'd like to add rotation of particles but I'm having problems with that.
Here is a jsfiddle which uses transformation matrix for rotation. As you can see in the picture (or fiddle) there are holes in the resulting image which I kinda expected from using this matrix.
nx = ~~ (xx * Math.cos(angle) + yy * Math.sin(angle) + cx);
ny = ~~ (xx * Math.sin(angle) - yy * Math.cos(angle) + cy);
But I don't know how to make this better, especially when I'm looking performance effecient solution?
jsfiddle demo
Image - square after rotation (square is used as a simple body):
Currently my backup is procedurally generated sprite animation which is prepared in advance with standard canvas states: save -> translate -> rotate -> restore.
Thank you very much for any directions you can give me.
The problem is that you are trying to map a single pixel to a single pixel. When you rotate an image, each pixel in the original can influence any of the surrounding pixels in the new image. You are effectively mapping the top left corner of each pixel to it's location in the new image, but you need map the center of each pixel to it's location in the new image and then check the overlap of this rotated pixel with that location, and the 8 surrounding pixels in the new image.
Here you can see the effect. The yellow dots are the centers of the pixel which find the "home" location for the pixel (i.e. where the majority of the influence will be placed). You then need to figure out the percentage of that pixel (the underlying blue/white grid) cell is covered by the original pixel (black box surrounding the yellow dot). Once you figure out the home location influence, you need to repeat that process for the 8 surrounding pixel with respect to current pixel in the original image. In your current code, you are using the top left corner of each pixel to find the home pixel for the new image. You should use the center of the pixel.
Since multiple iterations might affect the same pixel, you'll need to calculate the transformation in a buffer before drawing it to the final image. For pixels in the transformation that are not fully covered by pixels in the original image, figure out the percentage of the pixel that is covered and use that to influence the alpha channel. You'll have to take care when applying the pixels to the final image that you account for the alpha portion and blend with what's already there.

Quick and simple way to get min and max y for square within a rotated rectangle

So I'm trying to get the top left x,y values for the green box to crop an image that has been rotated into a square.
The green square can move left and right on the dotted line, so I'm able to get the x value, I'm just having a hard time getting the Y especially when the blue rectangle is a different aspect ratio.
So I know how much the blue rectangle has be rotated and with width and height, also the width and height of the bounding box and same for the green square.
So I need the min and max Y at a certain X value with a rotation between -10 - 10 degrees?
I'm using html and js right now.
the blue rectangle is a scrollable div that's rotated inside the square div so you can see a preview of the crop.
diagram:
http://i.stack.imgur.com/FwXjZ.jpg
thanks
You can setup a line equation for the top and bottom side of the rotated rectangle: y1 = mx + b1, resp. y2 = mx + b2
m is the slope, which is the tangent of the angle between the line and the x-axis.
b is the intercept (the y-value at which the line intersects the y-axis; b = y(0)).
Look at this site for more information.

Which algorithm to use for finding out whether a coordinate is in a specific area?

I want to know whether a point is in the "black" area of some image like the one below.
For the time being I created a large array like this (generated outside JavaScript):
area = [ [0,200], [0,201], [0,202], ..., [1,199], [1,200], ...]
to indicate which coordinates are black. Since this is getting very memory heavy for larger areas (I'm talking of image sizes of about 2000x2000 pixels), which kind of algorithm would you choose that is fast and not too memory hungry for finding out whether a specific coordinate is inside the black area?
You can draw the image to a canvas with same width and height as the image and then retrieve the pixelColor from the canvas at the specific point(x|y).
Here is a thread on how to retrieve the pixcel color:
Get pixel color from an image
This is how i retrieve the pixel color from the mouseposition and return a colorcode('#rrggbb'):
var pixelData = canvas.getContext('2d').getImageData(event.offsetX, event.offsetY, 1, 1).data;
var hex= '#' + valToHex(pixelData[0]) + valToHex(pixelData[1]) + valToHex(pixelData[2]);

Categories

Resources