How to calculate the height and width of an isometric rectangle/square
I'm writing an isometric tile game. Each tile is twice as wide as it is tall (w:h = 2:1). A开发者_运维百科ll tiles in a map are the same size and their width and heights are known (TileWidth and TileHeight).
There can be any number of columns (>0) and rows (>0).
I'm struggling to come up with a formula to calculate the width and height of the fully drawn map. This needs to be the distance from the very top to the very bottom and the extreme left to the extreme right. As the number of columns and rows can vary (and thus the map is not always a perfect diamond) it's proving very hard!
Good question! There's a not-too-obvious answer but it's easy to calculate:
Let's call the row axis "r" and the column axis "c", and consider the first picture, where the extent along the r axis is 5 and the extent along the c axis is 3.
The unit increment along the r axis, relative to the drawing plane, is at angle +30 = (cos 30°, sin 30°) = (sqrt(3)/2, 0.5), and the unit increment along the c axis is at -30 = (cos 30°, -sin 30°) = (sqrt(3)/2, -0.5).
You need to consider the two diagonals of your isometric rectangle. In the first picture, those diagonals are D1 = [+5*U along the r axis and +3*U along the c axis] and D2 = [+5*U along the r axis and -3*U along the c axis], where U is the tile length in the isometric plane. When transformed into the drawing plane, this becomes D1 = ((5+3)*sqrt(3)/2*U, (5-3)/2*U) = (4*sqrt(3)*U, 1*U) and D2 = ((5-3)*sqrt(3)/2*U, (5+3)/2*U) = (sqrt(3)*U, 4*U). The screen width and height, therefore, are the maximum of the two extents = 4*sqrt(3)*U, 4*U.
This can be generalized: if there are Nr rows and Nc columns, and the tile length is U, the extent of the diagonals of the rectangle in the drawing plane are D1 = ((Nr+Nc)*sqrt(3)/2*U, (Nr-Nc)/2*U) and D2 = ((Nr-Nc)*sqrt(3)/2*U, (Nr+Nc)/2*U), and the screen width and height, therefore, are:
W = U*(Nr+Nc)*sqrt(3)/2
H = U*(Nr+Nc)/2
The angles of the isometric projection are 60deg and 30deg. The actual width and height of a tile will be:
Wiso = TileWidth * Cos(30) + TileHeight * Cos(60)
Hiso = TileWidth * Sin(30) + TileHeight * Sin(60)
Now you can add multiply these numbers by the number of tiles per row and column to get the grid's size.
EDIT: looking at your images, it seems like the projection is not isometric (at least not what I learned in school), and the angles are 60deg to both sides, so replace the Cos(60)
with Cos(30)
and the Sin(60)
with Sin(30)
Another way to look at it:
Wgrid = TileWidth * Cos(30) * Ncols + TileHeight * Cos(30) * Nrows
Hgrid = TileWidth * Sin(30) * Ncols + TileHeight * Sin(30) * Nrows
If you start at the bottom and walk up the left side, you move up half the tile height for each column, then half the height for each row. Similarly if you start at the left and walk along the bottom edge, you move up half the tile width for each column, then half the width for each row.
So the width of the axis-aligned bounding box for the map is (rows+columns)*TileWidth/2
and the height is (rows+columns)*TileHeight/2
Why not use rotation equations as follows:
Suppose the tiles are not rotated, so the four corners have the following coordinates:
(0, 0, 0)
(w, 0, 0)
(0, h, 0)
(w, h, 0)
where
w = Number of Columns * Tile Width
h = Number of Rows * Tile Height
Now I suppose you have the projection matrix, so after applying it, you get 2D screen coordinates of the 4 3D points, and what you need to do is this:
- Get the minimum x-coordinate of all the points (after projection).
- Get the maximum x-coordinate of all the points (after projection).
- Get the minimum y-coordinate of all the points (after projection).
- Get the maximum y-coordinate of all the points (after projection).
Subtract 1 from 2, and you to get the width, and 3 from 4 to get the height.
Does that help?
I think you could do this with Pythagoras' theorem:
halfWidth = tileWidth / 2;
halfHeight = tileHeight / 2;
h = Math.sqrt((halfWidth * halfWidth ) * (halfHeight * halfHeight));
rowLength = rowSize * h;
colLength = colSize * h;
My maths is not great but h
should be the length of one side of a tile so you can then multiply that by the number of tiles.
精彩评论