I have a javascript program that places rectangles one at a time along walls in a room in counter-clockwise order. I use the coordinates of the rectangles corners for collision detection. It skips the placement of a rectangle if it intersects with another rectangle in the room.
(the room can be any shape so collisions can happen on any side of the rectangle)
However, I want to move the rectangle along the wall until it is no longer colliding instead of skipping it. My current idea is to move the rectangle 1 coordinate at a time in a loop until it no longer intersects, but it does not seem like a good solution for performance.
Is there a way to mathematically know how far in a given direction the rotated rectangle needs to be moved in order to no longer intersect another rotated rectangle?
Consider using of Separating Axis Theorem.
Two boxes (polygons in wide sense) don't intersect, if there exists some axis parallel to some box side, separating boxes, so the lie at distinct sides of this axis.
I've got arbitrary paper with good picture. At pages 16-17 we can see two boxes and some formulas to check for intersection.
You can express T - difference vector between box center as
T.x = pb.x - pa.x + t * dx
T.y = pb.y - pa.y + t * dy
where t is parameter (0 in the starting moment), and (dx, dy) is direction vector for B box moving (along the slanted wall at your picture).
Substituting T components into formula (note I changed > sign to =) we can get equation for parameter t corresponding to moment when Ax becomes separating axis.
| T • Ax | = WA + | ( WB*Bx ) • Ax | + |( HB*By ) • Ax |
If we make the same for other axes (Ay, Bx, By), we get 4 values of t, and the smallest positive one corresponds to minimal diplacement needed to separate the boxes.
Note that right part contains only constant values (for given setup), and we can easily calculate it using abs function, but left part contains variable, so we have to consider two cases (negative and positive dot product T • Ax) to find solution(s). Two possible solutions correspond to "left and right" box separation (anyway, you need smaller positive result)
I'm trying to find a more efficient way of determining which hexagon a point belongs to from the following:
an array of points - for the sake of argument, 10000 points.
an array of center points of hexagons, approximately 1000 hexagons.
every point will belong to exactly one hexagon, some (most) hexagons will be empty.
The hexagons form a perfect grid, with the point of one hexagon starting in the top left corner (it will overlap the edge of the total area).
My current solution works, but is rather slow n * (m log m) I think, where n=length(points) and m=length(hexagons).
I suspect I can do much better than this, one solution that comes to mind is to sort (just once) both the points and the hexagons by their distance to some arbitrary point (perhaps the middle, perhaps a corner) then iterate over the points and over a subset of the hexagons, starting from the first hexagon whose distance to this point is >= to the last hexagon matched. Similarly, we could stop looking at hexagons once the distance difference between the (point -> ref point) and (hexagon center -> ref point) is larger than the "radius" of the hexagon. In theory, since we know that every point will belong to a hexagon, I don't even have to consider this possibility.
My question is: Is there a Much better way of doing it than this? In terms of complexity, I think it's worst case becomes marginally better n * m but the average case should be very good, probably in the region of n * 20 (e.g., we only need to look at 20 hexagons per point). Below is my current inefficient solution for reference.
points.forEach((p) => {
p.hex = _.sortBy(hexes, (hex) => {
const xDist = Math.abs(hex.middle.x - p.x);
const yDist = Math.abs(hex.middle.y - p.y);
return Math.sqrt((xDist * xDist) + (yDist * yDist));
})[0];
});
For an arbitrary point, you can find the nearest hexagon center in two steps (assuming the same arrangement as that of Futurologist):
divide the abscissa by the horizontal spacing between the centers, and round to the nearest integer.
divide the ordinate by the half of the vertical spacing, and round to the nearest even or odd integer, depending on the parity found above.
consider this center and the six ones around it, and keep the closest to the target point.
This gives you the indexes of the tile, in constant time.
Just a suggestion: assume you have the centers of each regular hexagon from your regular hexagonal grid (if I have understood correctly, that's part of the information you have).
-----
/ \
- ----- -----------> x - axis
\ / \
----- -
/ \ /
- -----
\ / \
----- -
| \ /
| -----
|
|
V
y - axis
You can think that your coordinate system starts from the center of the hexagon in the upper left corner and the y coordinate axis runs vertically down, while the x axis runs from left to right horizontally. The centers of the hexagons from your regular hexagonal grid form an image of the regular square grid, where the integer vertices of the square grid are transformed into the centers of the polygons by simply multiplying the coordinates of points in the square grid by the 2 x 2 square matrix (a sheer metrix)
A = a*[ sqrt(3)/2 0;
1/2 1 ]
where a is a parameter of the hexagonal grid, the distance between the centers of two edge-adjacent hexagons. This provides a way to assign integer indices [m n] to the grid formed by the hexagonal centers. After that, if you are given a point with coordinates [x y] in the hexagonal grid, you can apply the inverse matrix of A
[u; v] = A^(-1)*[x; y]
where
A^(-1) = (2/(a*sqrt(3)))*[ 1 0 ;
-1/2 sqrt(3)/2 ]
([x; y] and [u; v] are column vectors) and then take m = floor(u) and n = floor(v) to determine the integer coordinates (also the indices) [m = floor(u), n = floor(v)] of the upper left corner of the square cell from the square grid (observe that we have chosen the coordinates for both grids to start from the upper left corner). Thus, your point [u, v] is in the square with vertices [m,n] [m+1, n] [m, n+1] [m+1, n+1]
which means that the original point [x y] is in one of the four hexagons whose centers have indices [m,n] [m+1, n] [m, n+1] [m+1, n+1]. So you can use that to check in which of the four hexagons the point [x y] is.
I hope this helps.
Update: Leaving the below comment for posterity
I am now using the code provided here: https://www.redblobgames.com/grids/hexagons/
A really important note, is that your hexagon grid MUST start with the first hexagons mid point at (0, 0) - if it doesn't you get extremely odd results from this, which at first glance appeared as rounding errors (even after accounting for the expected offset). For me, it didn't matter where the first hexagon was positioned, so I just set it to be (0, 0) and it worked great.
Old solution
I'm still hoping for an optimal solution, but I ended up rolling my own which needs only check 6 hexagons per point, with a little overhead (approximately sqrt(m)) needed in addition.
With approximately 3000 points, and 768 hexagons (of which 310 were populated), it correctly assigned the point to the hexagon 100% of the time (as checked against a brute force approach) and took 29 milliseconds, compared to ~840 with brute force.
To start with, I store the hexagons in a map where the key is "${column},${row}". The columns technically overlap, so for the 0th row, the 0th column starts at -0.5 * hexWidth, and for row 1, the 0th column starts at 0px.
Next, I start from the position of the top left hexagon, item "0,0", which should also be at position 0, and increment y by either the height of the hexagon, or the edge length of the hexagon accordingly. When the y is > the points y, I've found the probable row, I then check the row above and below.
For the column within the row, I take the both the Math.floor and Math.ceil of x / hexWidth.
Doing this gives 6 hexagons to check, from this point the solution is identical to the solution in the question.
In theory, this could be used to just look up the correct hexagon, using the x/y position. However in practice, this didn't work for me about 5% of the time with off by 1 errors, likely a rounding problem.
Some other things I looked at:
As suggested by #jason-aller, https://www.redblobgames.com/grids/hexagons/#rounding. Unfortunately, this seems to assume some form of transformation on the hex grid (rotations) and is not easy to follow - continually referencing functions which have yet to be defined.
QuadTree (various implementations) unfortunately, this returned approximately 100 "potential matches" for each point - so the performance improvement was not good. I'm aware that insertion order changes how useful QuadTree is, I tried natural order, sorted by distance from top, left and shuffled, they all performed equally badly. It's likely that an optimal solution with QuadTree would involve populating the tree with the item closest to the mid point, then the items 1/2 from the mid point to each corner, recursively. Too much like hard work for me!
I need to mimic an angled line being drawn between two html elements using another html element that's essentially flat (1 px height by 200 px wide) like a line. Here's an example.
In this example, I hard-coded the angle of the line using the CSS skewY transform to make the lines angle at roughly 10px intervals. The problem is I need to do this dynamically using javascript. While already knowing the origin and destination points, I'll be using jQuery to style the line using skewY which requires a number in degrees.
How does one figure out the angle of the skew in order to have it start and end at 2 exact pixel points? I'm guessing they'll be some algebra involved.
Thanks!
Mark
Given the known starting point, and the known ending point, and the fact that each line appears to be the longest side of a right angle triangle, I would think a bit of trigonometry could come into play.
Assumptions would be that you know the x distance between the start and the end (in your code 'one' and 'two') i.e. the horizontal - call this the adjacent, and that you should be able to establish the distance from the top (the distance from the first two, to nth two), call this the opposite then one could establish the angle (lets call it x) by SOHCAHTOA being the TOA part (or TAN angle = Opposite over adjacent) or TAN x = O/A or x = tan -1 (O/A). If I remember correctly the angle will be in radians, so will need to be converted to degrees (multiple by 180/pi)
Sample code
var O = //to be set
var A = //to be set
var x = Math.atan(O/A) * (180 / Math.PI)
I'm not a programmer primarily, so this might be a simple answer.
I'm working on a script in Illustrator where you select three points and then it does stuff. First it makes a triangle. Then, it recreates two of the line segments in the triangle and rotates them 90 degrees. Then, I find the intersect of those points so that I can make a circumcircle.
I'm actually moving along quite well, but the only problem I don't know how to solve at the moment is when two points that comprise the triangle have the same y-coordinates. When I make the perpendicular line, that line is vertical and therefore has no slope. It throws an error.
How do I account for a vertical slope with JavaScript? I was thinking about something along the lines of, "if the slope is NaN, then set the slope value to 9999999" or something like that, but this seemed a bit crude. Any better options?
You could normalise your gradient in the range -1 to 1. Anything larger than 1, or a NaN, is clamped at 1. The same goes for negative numbers, but with -1.
My thought was that you could draw a line that traversed the river and then if you knew the total distance of the river you divide the line's pixel length by the distance.
So if your line was 760px and the distance of the river was 20 miles then 760 / 20 = 38px = 1 mile.
Of course if my line was just a straight line or a series of lines this would be fairly simple. However, I would like my line to reflect the contours of the river and as such would be curved in places.
Firstly, is this a good method for plotting distance travelled along a river? If not what would work better (i have a feeling my maths is wrong!).
If this is a good method how would i take into account the curved nature of the line and how this might affect the pixel length of the line?
Calculating the length of a river is similar to calculating the Length of an Arc
.
Even if you draw the river exactly as you want it in an canvas(or in any Raster Image for that matter), and then count the amount of blue pixels, you would only be able to get an approximate answer as close as canvaswidth / riverdistance.
I wouldn't use miles (because its too crude). Use something shorter instead (I'd use meters, but ymmv).
Then just draw a line along the curvature of the river and count the pixels of that line, every pixel represents a given distance. (e.G. one pixel could represent 150 meters)