transformation of evenly spaced rectangular set of point - geometry

I have a set of evenly spaced point that forms a rectangle (sorry for the bad drawing, imagine all points are evenly spaced), and applying an angle, i want to go from left picture to right picture. The only point that does NOT move are the bottom left and the top right.
I guess i can deduce new locations of each point using tangent to get dx and dy. But i am not sur that i will end up with exactly what i want. And there may be a more elegent transformation to apply on each point ?

So we want to preserve two opposite vertices of rectangle and diagonal between them.
Let half-width of rectangle is w, half-height h, circle radius r. Let coordinate origin is at circle center.
Angle between diagonal and OX is
theta = atan(h/w)
After transformation angle between diagonal and low edge of new rectangle is
fi = alpha + theta
So we can find half-width of new rectangle
nw = r * cos(fi)
And coordinates of shifted vertex are
2*nw*cos(alpha) - w, -h - 2*nw*sin(alpha)
We want to find affine tranformation M that transform two vertices to the same points and the third vertex into coordinates above
|-w w w| |-w w 2*nw*cos(alpha) - w |
M * |-h h -h| = |-h h -h - 2*nw*sin(alpha)|
|1 1 1| |1 1 1|
To find M, we make inversion of the left matrix and multiply both sides by this inverse.
M = |nw*cos(alpha)/w w/h - nw*cos(alpha)/h 0|
|-nw*sin(alpha)/w 1 + nw*sin(alpha)/h 0|
|0 0 1|
Now we can transform all coordinates with this matrix and get rotated rectangle.
Example of coordinate transformation from my Delphi program generating picture below:
nX := Round(cx + x * cos(alpha)*nw/w + y * (w/h - cos(alpha)*nw / h));
nY := Round(cy - x * nw/w*sin(alpha) + y * (1 + nw/h * sin(alpha)));

Related

How do you calculate the x,y points of all corners of a square from two only a pair of x,y points (see pic)

I have the green x,y points, how would I get the missing red?
You can rotate the two known points of 90° around their midpoint.
In pseudo code:
// Evaluate the midpoint from the coordinates of points a and b,
h_x = (b_x - a_x) / 2;
h_y = (b_y - a_y) / 2;
m_x = a_x + h_x;
m_y = a_y + h_y;
// Apply a rotation of 90 degree around the midpoint to find c and d
c_x = m_x - h_y;
c_y = m_y + h_x;
d_x = m_x + h_y;
d_y = m_y - h_x;
This result can be formally derived in terms of homogeneous coordinates and transfomation matrices.
The midpoint m, expressed in homogeneous coordinates, can be calculated as
To rotate a vector around the origin of an angle α, we apply a rotation matrix like
If another center of rotation is needed (the midpoint, in our case), we need to translate from the original position to the origin, apply the rotation and translate back again. The translation matrices are
The complete transformation can be expressed as
Where
So that we can evaluate, let's say d, with
Q.e.d.

Cone normal vector

I have cone->p (vertex of the cone), cone->orient (axis vector), cone->k (half-angle tangent), cone->minm and cone->maxm (2 height values, for cone caps). Also I have point intersection which is on the cone. How do I find the cone (side surface) normal vector at intersection point using only these parameters?
Сame up with simpler method:
Find distance Dis from intersection point I to base P
Make axis orientation vector of length
D = Dis * sqrt(1+k^2)
and make point on axis at this distance
A = P + Normalized(Orient) * D
Now
Normal = I - A
Old answer:
Make orthogonal projection of point I (intersection) onto cone axis using vector `IP = I - P' and scalar (dot) product:
AxProj = P + Orient * dot(IP, Orient) / dot(Orient, Orient)
Vector from AxPr to I (perpendicular to axis):
AxPerp = I - AxProj
Vector, tangent to cone surface, using vector product:
T = IP x AxPerp
Vector, normal to cone surface:
N = T x IP
If I is the intersection point on the cone's surface and you know its coordinates, and P is the vertex of the cone, whose coordinates you also know, then this is enough:
Normal = (axis x PI) x PI
Normal = Normal / norm(Normal)
where axis is the vector aligned with the axis of the cone.

Tessellating hexagons over a rectangle

I have an infinite grid of hexagons, defined by a cubic (x y z) coordinate system like so:
I also have a viewport -- a rectangular canvas where I will draw the hexagons.
My issue is this. Because the grid of hexagons is infinite in all directions, I can't feasibly draw all of them at once. Therefore, I need to draw all the hexagons that are in the viewport, and ONLY those hexagons.
This image summarizes what I want to do:
In this image, purple-colored hexagons are those I want to render, while white-colored hexagons are those I don't want to render. The black rectangle is hte viewport -- all the hexagons that intersect with it are to be drawn. How would I find which hexagons to render (IE their xyz coordinates)?
Some other info:
I have a function that can recall a hexagon tile and draw it centered at position(x,y) in the viewport, given its cubic xyz coordinates. Therefore, all I should need is the xyz coords of each rectangle to draw, and I can draw them. This might simplify the problem.
I have formulas to convert from cubic hexagon coordinates to x/y coordinates, and back. Given the above diagram, r/g/b being the axes for the cubic coords with the image above, x and y being the cartesian coordinates, and s being the length of a hexagon's edge...
y = 3/2 * s * b
b = 2/3 * y / s
x = sqrt(3) * s * ( b/2 + r)
x = - sqrt(3) * s * ( b/2 + g )
r = (sqrt(3)/3 * x - y/3 ) / s
g = -(sqrt(3)/3 * x + y/3 ) / s
r + b + g = 0
Let's X0, Y0 are coordinates of top left corner, RectWidth is rectangle width, HexWidth = s * Sqrt(3/2) is hexagon width.
Find center of the closest hexagon r0, g0, b0, HX0, HY0. (Rect corner lies in this hexagon, because hexagons are Voronoy diagram cells). Remember horizontal and vertical shift DX = X0 - HX0, DY = Y0 - HY0
Draw horizontal row of Ceil(RectWidth/HexWidth) hexagons, incrementing r coordinate, decrementing f, and keeping b the same, ROWINC=(1,-1,0).
Note that if DY > HexWidth/2, you need extra top row with initial coordinates shifted up (r0, g0-1, b0+1)
Shift starting point by L=(0, 1, -1) if the DX < 0, or by R=(1, 0, -1) otherwise. Draw another horizontal row with the same ROWINC
Shift row starting point by alternative way (L after R, R after L). Draw horizontal rows until bottom edge is reached.
Check whether extra row is needed in the bottom.
You can think of the rectangular box in terms of constraints on an axis.
In the diagram, the horizontal lines correspond to b and your constraints will be of the form somenumber ≤ b and b ≤ somenumber. For example the rectangle might be in the range 3 ≤ b ≤ 7.
The vertical lines are a little trickier, but they are a “diagonal” that corresponds to r-g. Your constraints will be of the form somenumber ≤ r-g and r-g ≤ somenumber. For example it might be the range -4 ≤ r-g ≤ 5.
Now you have two axes with constraints on them, and you can form a loop. The easiest thing will be to have the outer loop use b:
for (b = 3; b ≤ 7; b++) {
…
}
The inner loop is a little trickier, because that's the diagonal constraint. Since we know r+g+b=0, and we know the value of b from the outer loop, we can rewrite the two-variable constraint on r-g. Express r+g+b=0 as g=0-r-b. Now substitute into r-g and get r-(0-r-b). Simplify r-(0-r-b) to 2*r-b. Instead of -4 ≤ r-g we can say -4 ≤ 2*r-b or -4+b ≤ 2*r or (-4+b)/2 ≤ r. Similarly, we can rearrange r-g ≤ 5 to 2*r-b ≤ 5 to r ≤ (5+b)/2. This gives us our inner loop:
for (b = 3; b ≤ 7; b++) {
for (r = (-4+b)/2; r ≤ (5+b)/2; r++) {
g = 0-b-r;
…
}
}
The last bit is to generalize, replacing the constants 3,7,-4,5 with the actual bounds for your rectangle.

How to get size of a rotated rectangle [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Calculate Bounding box coordinates from a rotated rectangle, Picture inside.
I have a rotated rectangle,
So how do i calculate the size of axis-aligned bounding box for the rotated rectangle in 2D Coordinates?
Attach Image
http://img88.imageshack.us/img88/503/rotp.png
i know x, y, o (angle)
but how do i get a, b
Thank you
a = abs(x * sin(o)) + abs(y * cos(o))
b = abs(x * cos(o)) + abs(y * sin(o))
To construct an axis-aligned bounding box, one must find the extreme points of the rotated box. i.e.,
given a rectangle 'P', given by points P1=(0,0), P2=(x,0), P3(x,y), P4(0,y), rotated 'R' degrees; find minX, maxX, minY, maxY, such that the box [(minX,minY),(maxX,maxY)] completely bounds the rotated 'P'.
+-------P3'----+maxY
| / \ |
P4------P3 | / \ |
| | rotate | / P2'
| | => by 'R' => P4' /|
| | degrees | \ / |
P1------P2 | \ / |
| \ / |
+-----P1'------+minY
minX maxX
The values for the bounding box are the minimum/maximum of the components of the rotated points P1'..P4'; thus,
minX=min(P1'[x],P2'[x],P3'[x],P4'[x])
maxX=max(P1'[x],P2'[x],P3'[x],P4'[x])
minY=min(P1'[y],P2'[y],P3'[y],P4'[y])
maxY=max(P1'[y],P2'[y],P3'[y],P4'[y])
For a discussion of 2D rotations, see http://en.wikipedia.org/wiki/Transformation_matrix#Rotation
Well you didn't give a whole lot of detail. I'm assuming you know that the height and width of the rectangle will give you the area no matter the rotation. If you only have the x,y data points then you use the sqrt((x1-x1)^2 + (y1-y2)^2). To get the length of a side.
You clarified your question so if you have a rectangle and you know the angle from the top left corner is rotated away from the top so the left side looks like this.
/
/
a = sine(alpha)*width
b = cosine(alpha)*width
c = sine(alpha)*height
d = cosine(alpha)*height
width = a + d
height = b + c
Be sure you get the angle right it is kind of hard to clarify it on here. If you get the other angle then it will come out to
width = b + c
height = a + d
For the axis aligned box of the rotated rectangle, you find the minimum and maximum of each of the 4 rotated coordintates. The minX and minY becomes 1 corner and the maxX and maxY becomes the other corner.
Use [Heron's Formula Triangle Area Calculator]
s = (a + b + c) / 2 or 1/2 of the perimeter of the triangle
A = SquareRoot(s * (s - a) * (s - b) * (s - c))
Where
a=SquareRoot((X1-X2)^2+(Y1-Y2)^2) [Side 1 Length]
b=SquareRoot((X1-X3)^2+(Y1-Y3)^2) [Side 2 Length]
c=SquareRoot((X2-X3)^2+(Y2-Y3)^2) [Side 3 Length]
X1,Y1,X2,Y2,X3,Y3 are the coordinations of any three points (Corners)
RectangleArea=2*A
Or Direct without [Heron's Formula Triangle Area Calculator], sequence of points are important here.
P1----P2
| |
P3----P4
a=SquareRoot((X1-X2)^2+(Y1-Y2)^2) [Side 1 Length]
b=SquareRoot((X1-X3)^2+(Y1-Y3)^2) [Side 2 Length]
RectangleArea=a*b
Calculate the area of the original rectangle. Area doesn't change under rotation.
It's a bit complicated, but for a rectangle, Area = b * h = length * width.

Simulating 3D 'cards' with just orthographic rendering

I am rendering textured quads from an orthographic perspective and would like to simulate 'depth' by modifying UVs and the vertex positions of the quads four points (top left, top right, bottom left, bottom right).
I've found if I make the top left and bottom right corners y position be the same I don't get a linear 'skew' but rather a warped one where the texture covering the top triangle (which makes up the quad) seems to get squashed while the bottom triangles texture looks normal.
I can change UVs, any of the four points on the quad (but only in 2D space, it's orthographic projection anyway so 3D space won't matter much). So basically I'm trying to simulate perspective on a two dimensional quad in orthographic projection, any ideas? Is it even mathematically possible/feasible?
ideally what I'd like is a situation where I can set an x/y rotation as well as a virtual z 'position' (which simulates z depth) through a function and see it internally calclate the positions/uvs to create the 3D effect. It seems like this should all be mathematical where a set of 2D transforms can be applied to each corner of the quad to simulate depth, I just don't know how to make it happen. I'd guess it requires trigonometry or something, I'm trying to crunch the math but not making much progress.
here's what I mean:
Top left is just the card, center is the card with a y rotation of X degrees and right most is a card with an x and y rotation of different degrees.
To compute the 2D coordinates of the corners, just choose the coordinates in 3D and apply the 3D perspective equations :
Original card corner (x,y,z)
Apply a rotation ( by matrix multiplication ) you get ( x',y',z')
Apply a perspective projection ( choose some camera origin, direction and field of view )
For the most simple case it's :
x'' = x' / z
y'' = y' / z
The bigger problem now is the texturing used to get the texture coordinates from pixel coordinates :
The correct way for you is to use an homographic transformation of the form :
U(x,y) = ( ax + cy + e ) / (gx + hy + 1)
V(x,y) = ( bx + dy + f ) / (gx + hy + 1)
Which is fact is the result of the perpective equations applied to a plane.
a,b,c,d,e,f,g,h are computed so that ( with U,V in [0..1] ) :
U(top'',left'') = (0,0)
U(top'',right'') = (0,1)
U(bottom'',left'') = (1,0)
U(bottom'',right'') = (1,1)
But your 2D rendering framework probably uses instead a bilinear interpolation :
U( x , y ) = a + b * x + c * y + d * ( x * y )
V( x , y ) = e + f * x + g * y + h * ( x * y )
In that case you get a bad looking result.
And it is even worse if the renderer splits the quad in two triangles !
So I see only two options :
use a 3D renderer
compute the texturing yourself if you only need a few images and not a realtime animation.

Resources