I am writing a bilinear interpolation method.
This method can be abstract by solve the equation A*x = b, A is a 4x4 matrix below:
1 x1 y1 x1*y1
1 x2 y2 x2*y2
1 x3 y3 x3*y3
1 x4 y4 x4*y4
Here, (x1, y1), (x2, y2), (x3, y3) and (x4, y4) is four points containing the dst interpolation point.
My problem is when det(A) = 0(then x! = A-1*b), what is the quadrangle looks like?
The determinant becomes 0 when one of the rows or columns can be expressed as a linear combination of the others. Using columns, this equation must hold for some constants a, b, c for each of the four points:
a*1 + b*x + c*y + xy = 0
This is the equation a hyperbola with asymptotes parallel to the axis, so the determinant is zero if and only if the four points fall on the same hyperbola.
For example, if you pick the rectangle (-2, -1), (-1, -2), (1, 2), (2, 1) the determinant will be zero since the points fall on the hyperbola defined by t → (t, 2/t).
Another way to look at it: you are free to pick any 3 points. The three points define a unique hyperbola. The determinant is 0 if and only if you pick the fourth point from that hyperbola.
Joni's answer above is entirely correct, but here's a physical interpretation that you might like:
Picture a square as a well-behaved quadrilateral defined by the following four points: 1 = (0,0), 2 = (1,0), 3 = (1, 1), and 4 = (0, 1).
If you start skewing it by anchoring points 1 and 2 but tugging point 3 to the right in such a way that the sides remain the same length, but the angle between the x-axis and the line segment between points 2 and 3 changes from 90 degrees to 180 and the angle between the x-axis and the line segment between points 1 and 4 changes from 90 degrees to 0, the determinant will approach zero as the angle increases. When you have points 1 = (0,0), 2 = (1, 0), 3 = (2,0), and 4 = (1,0) the quad will be collapsed to a line segment and the determinant will be zero.
You can run this experiment with your matrix and see if I'm correct.
Related
I have a line between two points a and b (3d vectors) and a third point p (from scalar projection).
I want to determine if the third point p is on the line between a and b or not between them.
What is the most efficient algorithm for the LuaJIT? Other languages would be fine too, but efficiency is important
Thanks to numberZero I got this code and it seems to work
function vec3d:is_between(a, b)
local ab = b - a
local ap = self - a
local lp = ap:len()
local lb = ab:len()
local dot = ap:dot(ab) / (lp * lb)
return lp < lb and dot > 0.95
end
If you already know the three points are collinear, you could compute the vector AP from a to p and the vector AB from a to b. If p is between a and b, then the dot product of AP and AB will equal 1 (i.e. the vectors point in the same direction) and the vector magnitude of AP will be less than that of AB.
If you don't know whether the points are collinear, it's easy to check. You can determine the collinearity of three points xi =
(xi, yi, zi) for i = 1, 2, 3 by implementing a test on the ratio of distances:
x2 - x1 : y2 - y1 : z2 -
z1 = x3 - x1 : y3 -
y1 : z3 - z1.
as explained in this Wolfram Mathworld article on Collinearity. From the same article, an even easier condition
is obtained by noting that the area of a triangle determined by three points will be zero iff they are collinear (including the degenerate cases of two or all three points being concurrent), i.e....in expanded form
x1( y2 - y3 ) + x2( y3 -
y1) + x3( y1 - y2 ) = 0.
If you know that the points lie on a single line, you may just calculate a dot product, and if 0 ≤ 〈AB, AP〉 ≤ 〈AB, AB〉, then P is between A and B. But note that if P is not exactly on the line, this method may give strange results. But it should be the fastest.
You may also want to calculate 2 values, distance from P to AB and (orthogonal) projection of AP onto AB. The latter is AP_AB = 〈AP, AB〉 / 〈AB, AB〉 (in AB units, so that if AP and AB are collinear, AP = AB * AP_AB), and the former is ρ(P, AB) = ρ(AP, AB * AP_AB) = |AP - AB * AP_AB|. So, if the ρ(P, AB) is small, you decide that if 0 ≤ AP_AB ≤ 1, then P is between A and B
I have line segment with start s(x1,y1) and end e(x2,y2). I have calculated distance between s and e by using euclidean distance
d = sqrt((x1-x2)(x1-x2) + (y1-y2)(y1-y2))
How to find out point on the line segment at distance d1 (0 < d1< d)?
The main theme of linearity is that everything is proportional.
d1 is d1/d fraction of the way from 0 to d.
Therefore, the point, p, that you are looking for is the same fraction of
the way from s to e. So let r = d1/d. Then
p = (x1 + r*(x2-x1), y1 + r*(y2-y1))
Notice that when r equals 0, p is (x1 + 0*(x2-x1), y1 + 0*(y2-y1)) = (x1, y1) = s. And when r equals 1, p is e = (x2, y2). As r goes from 0 to 1, p goes from s to t linearly -- that is, as a linear function of r.
parametric Line is defined like this:
x(t)=x1+(x2-x1)*t;
y(t)=y1+(y2-y1)*t;
where t is parameter in range <0.0,1.0>
if t=0.0 then the result is giving point (x1,y1)
if t=1.0 then the result is giving point (x2,y2)
So if you need point at d distance from start then:
D=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
x(d)=x1+(x2-x1)*d/D;
y(d)=y1+(y2-y1)*d/D;
where D is line length
and d is distance from start point
I need assistance in simulating movement between 2 points in a plane. Consider two points P1:(x,y1) and P2:(x2,y2). I compute the distance between P1 and P2, say D, and I choose a random velocity, say V. Next, I compute the time required to move from P1 to P2, say T. Finally, I compute the equation of the straight line between P1 and P2 as y = mx + b.
For example, let T = 10 seconds. For the first 9 seconds, I would like to generate points per second on the straight line until I reach point P2 at the 10th second. Could you please assist me in doing so.
The best approach is to use parametric equations
x = x1 + t*(x2 - x1)
y = y1 + t*(y2 - y1)
where t is the "time" parameter going from 0 to 1 (0.5 means for example halfway).
If you also like your movement to be "soft" (starting from zero velocity, then accelerating then slowing down and stopping on the arrival point) you can use this modified equation
w = 3*t*t - 2*t*t*t
x = x1 + w*(x2 - x1)
y = y1 + w*(y2 - y1)
The following is a plot of the w curve compared to a linear distribution t with 11 points (t=0.0, 0.1, ... 0.9, 1.0):
I have two squares, S1 = (x1,y1,x2,y2) and S2 = (a1,b1,a2,b2)
I'm looking for the A transformation matrix with which
A * S1 = S2
As far as I see, A is an affine 3x3 matrix, so I have 9 unknown values.
How can I calculate these values?
thanks and best,
Viktor
There are really only four unknown values here. A rotation angle, a scale factor and an x and y translation. Of your three by three matrix the bottom row is always 0,0,1 which reduces you to six unknowns. The right hand column will be Tx,Ty,1 which are your translations (and the 1 we already know about).
The two by two "matrix" left will be your rotation and scaling. This will (off the top of my head) be something like:
ACos(B), -Asin(B)
ASin(B), aCos(B)
So in total:
ACos(B), -Asin(B), Tx
ASin(B), ACos(B), Ty
0 , 0 , 1
You extend your co-ordinate matrices with the 1 on the end of each co-ordinate to give 2x3 matrices and they then multiply to give you the four equations you need to solve for the four variables. That is left as an exercise for the reader.
A transformation matrix is a factor of scaling matrix Ss, transition matrix St and rotation matrix Sr.
Assume the old point is Po is (Xo,Yo) and as vector will be represented as (Xo Yo 1)' same for the new point Pn
Then Pnv =SsStSrPov
Where Sx is
Sx 0 0
0 Sy 0
0 0 1
St is
1 0 Tx
0 1 Ty
0 0 1
Sr is
Cos(th) -Sin(th) 0
Sin(th) Cos(th) 0
0 0 1
Now back to your question. if two point are giving to represent a rectangle we can just find the parameter of two matrix and the third one will be an identity matrix.
Rect1 is represented as Top-Left point P11 and Bottom-Right Point P12
Rect2 is represented as Top-Left point P21 and Bottom-Right Point P22
S=Ss*St
Sx 0 Tx
0 Sy Ty
0 0 1
Now you have 4 missing parameters and 4 set of equations
P21=S*P11
P22=S*P12
X[P21] =Sx*X[P11]+Tx
Y[P21] =Sy*Y[P11]+Ty
X[P22] =Sx*X[P12]+Tx
Y[P22] =Sy*Y[P12]+Ty
Solve it and you'll get your answer.
and if you have transition and rotation then
S=Sr*St.
Cos(th) -Sin(th) Tx
Sin(th) Cos(th) Ty
0 0 1
Now you have 3 missing parameters and 4 set of equations
P21=S*P11
P22=S*P12
X[P21] =Cos(th)*X[P11]-Sin(th)*Y[P11]+Tx
Y[P21] =Sin(th)*X[P11]+Cos(th)*Y[P11]+Ty
X[P22] =Cos(th)*X[P11]-Sin(th)*Y[P12]+Tx
Y[P22] =Sin(th)*X[P11]+Cos(th)*Y[P12]+Ty
Replace Cos(th) with A and Sin(th) With B and solve the equations.
X[P21] =A*X[P11]-B*Y[P11]+Tx
Y[P21] =B*X[P11]+A*Y[P11]+Ty
X[P22] =A*X[P11]-B*Y[P12]+Tx
Y[P22] =B*X[P11]+A*Y[P12]+Ty
Check if its correct A^2+B^2 =? 1 if is true then th = aCos(A)
The last part of the solution, if you'll have all three matrixes, then S=SrStSs is
Sx*sin(th) -Sx*cos(th) Tx
Sy*cos(th) Sy*sin(th) Ty
0 0 1
Now we have 5 missing variables and we need 6 different set of equations to solve it. which is mean 3 points from each rectangle.
You shouldn't have a 3x3 matrix if you're just looking to transform a 2D object. What you're looking for is a 2x2 matrix that solves A*S1=S2. This can be done in many different ways; in MATLAB, you'd do a S2/S1 (right matrix division), and generally this performs some kind of Gaussian elimination.
How can I calculate these values?
When applied to 2d/3d transformations, matrix can be represented a coordinate system, unless we are talking about projections.
Matrix rows (or columns, depending on notation) form axes of a new coordinate system, in which object will be placed placed if every object vertex is multiplied by the matrix. Last row (or columne, depending on notation) points to the center of the new coordinate system.
Standard OpenGL/DirectX transformation matrix (NOT a projection matrix):
class Matrix{//C++ code
public:
union{
float f[16];
float m[4][4];
};
};
Can be represented as combination of 4 vectors vx (x axis of the new coordinate system), vy(y axis of a new coordinate system), vz(z axis of a new coordinate system), and vp (center of the new system). Like this:
vx.x vx.y vx.z 0
vy.x vy.y vy.z 0
vz.x vz.y vz.z 0
vp.x vp.y vp.z 1
All "calculate rotation matrix", "calculate scale matrix", etc go down to this idea.
Thus, for 2d matrix, you'll have 3x3 matrix that consists of 3 vectors - vx, vy, vp, because there is no z vector in 2d. I.e.:
vx.x vx.y 0
vy.x vy.y 0
vp.x vp.y 1
To find a transform that would transform quad A into quad B, you need to find two transforms:
Transform that will move quad A into origin (i.e. at point zero), and convert it into quad of fixed size. Say, quad (rectangle) whose one vertex x = 0, y = 0, and whose vertices are located at (0, 1), (1, 0), (1, 1).
Transform that turns quad of fixed size into quad B.
You CANNOT do that it this way if opposite edges of quad are not parallel. I.e. parallelograms are fine, but random 4-sided polygons are not.
A quad can be represented by base point (vp) which can be any vertex of the quad and two vectors that define quad sizes (direction of the edge multiplied by edge's length). I.e. "up" vector and "side" vector. Which makes it a matrix:
side.x side.y 0
up.x up.y 0
vp.x vp.y 1
So, multiplying a quad (vp.x = 0, vp.y = 0, side.x = 1, side.y = 0, up.x = 0, up.y = 1) by this matrix will turn original quad into your quad. Which means, that in order to transform
quad A into quad B, you need to do this:
1) make a matrix that would transform "base 1unit quad" into quad A. Let's call it matA.
2) make a matrix that would transform "base 1 unit quad" into quad B. let's call it matB.
3) invert matA and store result into invMatA.
4) the result matrix is invMatA * matB.
Done. If you multiply quad A by result matrix, you'll get quad B. This won't work if quads have zero widths or heights, and it won't work if quads are not parallelograms.
This is hard to understand, but I cannot to make it simpler.
What do you mean by S1 = (x1,y1,x2,y2)?
Do they represent the top-left and bottom-right corners of the square?
Also, can you guarantee there's only rotation between the squares or do you need a full affine transformation which allows for scaling, skewing, and translation?
Or do you also need a perspective transformation?
Only if it's a perspective transformation, will you need 3x3 matrix with 8 dof as you've mentioned in your post.
I need to calculate the overlap (amount or yes/no) that two rectangles make on a special x/y grid. The grid is 500x500 but the sides and corners connect (are continuous). So the next point after 499 becomes 0 again.
In a previous question I asked for a way to calculate the distance between two points in this grid. This turned out to be the Euclidean distance:
sqrt(min(|x1 - x2|, gridwidth - |x1 - x2|)^2 + min(|y1 - y2|, gridheight - |y1-y2|)^2)
What is the good mathematical way of calculating if two rectangles (defined by a point (x,y), width and height) have overlap in this grid?
Rectangle-1 ([x=0,y=0], w=20, h=20) and Rectangle-2 ([x=495,y=0], w=10, h=10) should have overlap. The overlapping rectangle (not really needed but) should be ([x=0,y=0], w=5, h=10)
First, compute the x and y range for each rectangle
(because you have a torus geometry do it mod gridsize).
So, given your Rectangle-1, compute:
x1 = x = 0, x2 = x + w = 20
y1 = y = 0, y2 = y + h = 20
Same for Rectangle-2:
x3 = 495, x4 = 505 mod 500 = 5
y3 = 0, y4 = 10
Create the x and y "regions" for each rectangle:
Reactangle-1: x-regions: (0, 20)
y-regions: (0, 20)
Rectangle-2: x-regions: (495, 500), (0, 5)
y-regions: (0, 10)
If any (both) x and y regions between the two rectangles have a non-null intersection, then your rectangles overlap.
Here the (0, 20) x-region of Rectangle-1 and the (0, 5) x-region of Rectangle-2 have a non-null intersection and so do the (0, 20) and (0, 10) y-regions.