Can someone explain the mat4.translate function from glMatrix? - matrix

Does anyone know why glmatrix ( 1.x ) defines mat4.translate like this:
/**
* Translates a matrix by the given vector
*
* #param {mat4} mat mat4 to translate
* #param {vec3} vec vec3 specifying the translation
* #param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
*
* #returns {mat4} dest if specified, mat otherwise
*/
mat4.translate = function (mat, vec, dest) {
var x = vec[0], y = vec[1], z = vec[2],
a00, a01, a02, a03,
a10, a11, a12, a13,
a20, a21, a22, a23;
if (!dest || mat === dest) {
mat[12] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12];
mat[13] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13];
mat[14] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14];
mat[15] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15];
return mat;
}
a00 = mat[0]; a01 = mat[1]; a02 = mat[2]; a03 = mat[3];
a10 = mat[4]; a11 = mat[5]; a12 = mat[6]; a13 = mat[7];
a20 = mat[8]; a21 = mat[9]; a22 = mat[10]; a23 = mat[11];
dest[0] = a00; dest[1] = a01; dest[2] = a02; dest[3] = a03;
dest[4] = a10; dest[5] = a11; dest[6] = a12; dest[7] = a13;
dest[8] = a20; dest[9] = a21; dest[10] = a22; dest[11] = a23;
dest[12] = a00 * x + a10 * y + a20 * z + mat[12];
dest[13] = a01 * x + a11 * y + a21 * z + mat[13];
dest[14] = a02 * x + a12 * y + a22 * z + mat[14];
dest[15] = a03 * x + a13 * y + a23 * z + mat[15];
return dest;
};
It looks like the vector values are multiplied (scaled) by the directional vectors ( dir, left, up ) of the matrix. But I don't understand why. Also why is mat[15] assigned. I thought it should always be 1...
I am using this most of the time and I am quite happy:
mat4.translate_alt = function (mat, vec, factor) {
factor = factor || 1;
mat[12] += vec[0]*factor;
mat[13] += vec[1]*factor;
mat[14] += vec[2]*factor;
}
When should I use mat4.translate and when is my mat4.translate_alt enough ?

mat4.translate translates a matrix with a given vector (vec3), which is the same as multiplying with a translation matrix.
Another way to look at it is to say mat4.translate = mat4.multiply(someMatrix, mat4.create_translate_matrix(someVec3)) (pseudo-code).

Related

why is my double pendulum programm isn't working in p5js?

var angle1 = 45;
var angle2 = 0;
var L1 = 200;var L2 = 200;
var m1 = 1;
var m2 = 1;
var angleV1 = 0;
var angleV2 = 0;
var g = 1;
var angleA1 =
((-g * (2 * m1 + m2) * sin(angle1) -
m2 * g * sin(angle1 - angle2) -
2 *
sin(angle1 - angle2) *
m2 *
(angleV2 * angleV2 * L2 +
angleV1 * angleV1 * L1 * cos(angle1 - angle2))) /
L1) *
(2 * m1 + m2 - m2 * cos(2 * angle1 - 2 * angle2));
var angleA2 =
((2 *
sin(angle1 - angle2) *
(angleV1 * angleV1 * L1 * (m1 + m2) +
g * (m1 + m2) * cos(angle1) +
angle2 * angle2 * L2 * m2 * cos(angle1 - angle2))) /
L2) *
(2 * m1 + m2 - m2 * cos(2 * angle1 - 2 * angle2));
angleV1 += angleA1;
angle1 += angleV1;
angleV2 += angleA2;
angle2 += angleV2;
var x1 = sin(angle1) * L1;
var y1 = cos(angle1) * L1;
var x2 = x1 + sin(angle2) * L2;
var y2 = y1 + cos(angle2) * L2;
line(0, 0, x1, y1);
line(x1, y1, x2, y2);

Rotate an image with bicubic interpolation without imrotate

I have implemented a code for image warping using bilinear interpolation:
Matlab image rotation
I would like to improve the code by using bicubic interpolation to rotate the image WITHOUT using the built-in functions like imrotate or imwarp and interp functions in MATLAB.
I successfully managed to implement a full working example.
Code is based on Anna1994's code: Matlab image rotation
Biqubic code is also based on Java (and C++) implementation posted here: http://www.paulinternet.nl/?page=bicubic
The following code applies image rotation example using biqubic interpolation:
function BicubicInterpolationTest()
close all;
% clear all;
img = 'cameraman.tif';
input_image =double(imread(img))./255;
H=size(input_image,1); % height
W=size(input_image,2); % width
th=120*pi/180; %Rotate 120 degrees
s0 = 2;
s1 = 2;
x0 = -W/2;
x1 = -H/2;
T=[1 0 x0 ; ...
0 1 x1 ; ...
0 0 1];
RST = [ (s0*cos(th)) (-s1*sin(th)) ((s0*x0*cos(th))-(s1*x1*sin(th))); ...
(s0*sin(th)) (s1*cos(th)) ((s0*x0*sin(th))+(s1*x1*cos(th))); ...
0 0 1];
M=inv(T)*RST;
N = inv(M);
output_image=zeros(H,W,size(input_image,3));
for i=1:W
for j=1:H
x = [i ; j ; 1];
y = N * x;
a = y(1)/y(3);
b = y(2)/y(3);
%Nearest neighbor
% a = round(a);
% b = round(b);
%Bilinear interpolation (applies RGB image):
% x1 = floor(a);
% y1 = floor(b);
% x2 = x1 + 1;
% y2 = y1 + 1;
% if ((x1 >= 1) && (y1 >= 1) && (x2 <= W) && (y2 <= H))
% %Load 2x2 pixels
% i11 = input_image(y1, x1, :); %Top left pixel
% i21 = input_image(y2, x1, :); %Bottom left pixel
% i12 = input_image(y1, x2, :); %Top right pixel
% i22 = input_image(y2, x2, :); %Bottom right pixel
%
% %Interpolation wieghts
% dx = x2 - a;
% dy = y2 - b;
%
% %Bi-lienar interpolation
% output_image(j, i, :) = i11*dx*dy + i21*dx*(1-dy) + i12*(1-dx)*dy + i22*(1-dx)*(1-dy);
% end
x1 = floor(a);
y1 = floor(b);
%Bicubic interpolation (applies grayscale image)
if ((x1 >= 2) && (y1 >= 2) && (x1 <= W-2) && (y1 <= H-2))
%Load 4x4 pixels
P = input_image(y1-1:y1+2, x1-1:x1+2);
%Interpolation wieghts
dx = a - x1;
dy = b - y1;
%Bi-bicubic interpolation
output_image(j, i) = bicubicInterpolate(P, dx, dy);
end
end
end
imshow(output_image);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Verify implementation by comparing with Matalb build in function imwarp:
tform = affine2d(M');
ref_image = imwarp(input_image, tform, 'OutputView', imref2d(size(input_image)), 'Interp', 'cubic');
figure;imshow(ref_image)
figure;imshow(output_image - ref_image)
max_diff = max(abs(output_image(:) - ref_image(:)));
disp(['Maximum difference from imwarp = ', num2str(max_diff)]);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%http://www.paulinternet.nl/?page=bicubic
%double cubicInterpolate (double p[4], double x) {
% return p[1] + 0.5 * x*(p[2] - p[0] + x*(2.0*p[0] - 5.0*p[1] + 4.0*p[2] - p[3] + x*(3.0*(p[1] - p[2]) + p[3] - p[0])));
%}
function q = cubicInterpolate(p, x)
q = p(2) + 0.5 * x*(p(3) - p(1) + x*(2.0*p(1) - 5.0*p(2) + 4.0*p(3) - p(4) + x*(3.0*(p(2) - p(3)) + p(4) - p(1))));
%http://www.paulinternet.nl/?page=bicubic
% double bicubicInterpolate (double p[4][4], double x, double y) {
% double arr[4];
% arr[0] = cubicInterpolate(p[0], y);
% arr[1] = cubicInterpolate(p[1], y);
% arr[2] = cubicInterpolate(p[2], y);
% arr[3] = cubicInterpolate(p[3], y);
% return cubicInterpolate(arr, x);
% }
function q = bicubicInterpolate(p, x, y)
q1 = cubicInterpolate(p(1,:), x);
q2 = cubicInterpolate(p(2,:), x);
q3 = cubicInterpolate(p(3,:), x);
q4 = cubicInterpolate(p(4,:), x);
q = cubicInterpolate([q1, q2, q3, q4], y);
I verified implementation by comparing to Matalb build in function imwarp
Result:
The following example uses the "CachedBicubicInterpolator" code version, and also supports RGB image:
function BicubicInterpolationTest2()
close all;
% clear all;
img = 'peppers.png';
input_image = double(imread(img))./255;
H=size(input_image,1); % height
W=size(input_image,2); % width
th=120*pi/180; %Rotate 120 degrees
s0 = 0.8;
s1 = 0.8;
x0 = -W/2;
x1 = -H/2;
T=[1 0 x0 ; ...
0 1 x1 ; ...
0 0 1];
RST = [ (s0*cos(th)) (-s1*sin(th)) ((s0*x0*cos(th))-(s1*x1*sin(th))); ...
(s0*sin(th)) (s1*cos(th)) ((s0*x0*sin(th))+(s1*x1*cos(th))); ...
0 0 1];
M=inv(T)*RST;
N = inv(M);
output_image=zeros(H,W,size(input_image,3));
for i=1:W
for j=1:H
x = [i ; j ; 1];
y = N * x;
a = y(1)/y(3);
b = y(2)/y(3);
x1 = floor(a);
y1 = floor(b);
%Bicubic interpolation (applies grayscale image)
if ((x1 >= 2) && (y1 >= 2) && (x1 <= W-2) && (y1 <= H-2))
%Load 4x4 pixels
P = input_image(y1-1:y1+2, x1-1:x1+2, :);
%Interpolation wieghts
dx = a - x1;
dy = b - y1;
%Bi-bicubic interpolation
output_image(j, i, :) = bicubicInterpolate(P, dx, dy);
end
end
end
imshow(output_image);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Verify implementation by comparing with Matalb build in function imwarp:
tform = affine2d(M');
ref_image = imwarp(input_image, tform, 'OutputView', imref2d(size(input_image)), 'Interp', 'cubic');
figure;imshow(ref_image)
figure;imshow(abs(output_image - ref_image), []);impixelinfo
max_diff = max(abs(output_image(:) - ref_image(:)));
disp(['Maximum difference from imwarp = ', num2str(max_diff)]);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [p0, p1, p2, p3] = list4(P)
P = squeeze(P);
p0 = P(1, :);
p1 = P(2, :);
p2 = P(3, :);
p3 = P(4, :);
%http://www.paulinternet.nl/?page=bicubic
% public void updateCoefficients (double[][] p) {
% a00 = p[1][1];
% a01 = -.5*p[1][0] + .5*p[1][2];
% a02 = p[1][0] - 2.5*p[1][1] + 2*p[1][2] - .5*p[1][3];
% a03 = -.5*p[1][0] + 1.5*p[1][1] - 1.5*p[1][2] + .5*p[1][3];
% a10 = -.5*p[0][1] + .5*p[2][1];
% a11 = .25*p[0][0] - .25*p[0][2] - .25*p[2][0] + .25*p[2][2];
% a12 = -.5*p[0][0] + 1.25*p[0][1] - p[0][2] + .25*p[0][3] + .5*p[2][0] - 1.25*p[2][1] + p[2][2] - .25*p[2][3];
% a13 = .25*p[0][0] - .75*p[0][1] + .75*p[0][2] - .25*p[0][3] - .25*p[2][0] + .75*p[2][1] - .75*p[2][2] + .25*p[2][3];
% a20 = p[0][1] - 2.5*p[1][1] + 2*p[2][1] - .5*p[3][1];
% a21 = -.5*p[0][0] + .5*p[0][2] + 1.25*p[1][0] - 1.25*p[1][2] - p[2][0] + p[2][2] + .25*p[3][0] - .25*p[3][2];
% a22 = p[0][0] - 2.5*p[0][1] + 2*p[0][2] - .5*p[0][3] - 2.5*p[1][0] + 6.25*p[1][1] - 5*p[1][2] + 1.25*p[1][3] + 2*p[2][0] - 5*p[2][1] + 4*p[2][2] - p[2][3] - .5*p[3][0] + 1.25*p[3][1] - p[3][2] + .25*p[3][3];
% a23 = -.5*p[0][0] + 1.5*p[0][1] - 1.5*p[0][2] + .5*p[0][3] + 1.25*p[1][0] - 3.75*p[1][1] + 3.75*p[1][2] - 1.25*p[1][3] - p[2][0] + 3*p[2][1] - 3*p[2][2] + p[2][3] + .25*p[3][0] - .75*p[3][1] + .75*p[3][2] - .25*p[3][3];
% a30 = -.5*p[0][1] + 1.5*p[1][1] - 1.5*p[2][1] + .5*p[3][1];
% a31 = .25*p[0][0] - .25*p[0][2] - .75*p[1][0] + .75*p[1][2] + .75*p[2][0] - .75*p[2][2] - .25*p[3][0] + .25*p[3][2];
% a32 = -.5*p[0][0] + 1.25*p[0][1] - p[0][2] + .25*p[0][3] + 1.5*p[1][0] - 3.75*p[1][1] + 3*p[1][2] - .75*p[1][3] - 1.5*p[2][0] + 3.75*p[2][1] - 3*p[2][2] + .75*p[2][3] + .5*p[3][0] - 1.25*p[3][1] + p[3][2] - .25*p[3][3];
% a33 = .25*p[0][0] - .75*p[0][1] + .75*p[0][2] - .25*p[0][3] - .75*p[1][0] + 2.25*p[1][1] - 2.25*p[1][2] + .75*p[1][3] + .75*p[2][0] - 2.25*p[2][1] + 2.25*p[2][2] - .75*p[2][3] - .25*p[3][0] + .75*p[3][1] - .75*p[3][2] + .25*p[3][3];
% }
% public double getValue (double x, double y) {
% double x2 = x * x;
% double x3 = x2 * x;
% double y2 = y * y;
% double y3 = y2 * y;
%
% return (a00 + a01 * y + a02 * y2 + a03 * y3) +
% (a10 + a11 * y + a12 * y2 + a13 * y3) * x +
% (a20 + a21 * y + a22 * y2 + a23 * y3) * x2 +
% (a30 + a31 * y + a32 * y2 + a33 * y3) * x3;
% }
function q = bicubicInterpolate(P, x, y)
[p00, p01, p02, p03] = list4(P(1, :, :));
[p10, p11, p12, p13] = list4(P(2, :, :));
[p20, p21, p22, p23] = list4(P(3, :, :));
[p30, p31, p32, p33] = list4(P(4, :, :));
a00 = p11;
a01 = -.5*p10 + .5*p12;
a02 = p10 - 2.5*p11 + 2*p12 - .5*p13;
a03 = -.5*p10 + 1.5*p11 - 1.5*p12 + .5*p13;
a10 = -.5*p01 + .5*p21;
a11 = .25*p00 - .25*p02 - .25*p20 + .25*p22;
a12 = -.5*p00 + 1.25*p01 - p02 + .25*p03 + .5*p20 - 1.25*p21 + p22 - .25*p23;
a13 = .25*p00 - .75*p01 + .75*p02 - .25*p03 - .25*p20 + .75*p21 - .75*p22 + .25*p23;
a20 = p01 - 2.5*p11 + 2*p21 - .5*p31;
a21 = -.5*p00 + .5*p02 + 1.25*p10 - 1.25*p12 - p20 + p22 + .25*p30 - .25*p32;
a22 = p00 - 2.5*p01 + 2*p02 - .5*p03 - 2.5*p10 + 6.25*p11 - 5*p12 + 1.25*p13 + 2*p20 - 5*p21 + 4*p22 - p23 - .5*p30 + 1.25*p31 - p32 + .25*p33;
a23 = -.5*p00 + 1.5*p01 - 1.5*p02 + .5*p03 + 1.25*p10 - 3.75*p11 + 3.75*p12 - 1.25*p13 - p20 + 3*p21 - 3*p22 + p23 + .25*p30 - .75*p31 + .75*p32 - .25*p33;
a30 = -.5*p01 + 1.5*p11 - 1.5*p21 + .5*p31;
a31 = .25*p00 - .25*p02 - .75*p10 + .75*p12 + .75*p20 - .75*p22 - .25*p30 + .25*p32;
a32 = -.5*p00 + 1.25*p01 - p02 + .25*p03 + 1.5*p10 - 3.75*p11 + 3*p12 - .75*p13 - 1.5*p20 + 3.75*p21 - 3*p22 + .75*p23 + .5*p30 - 1.25*p31 + p32 - .25*p33;
a33 = .25*p00 - .75*p01 + .75*p02 - .25*p03 - .75*p10 + 2.25*p11 - 2.25*p12 + .75*p13 + .75*p20 - 2.25*p21 + 2.25*p22 - .75*p23 - .25*p30 + .75*p31 - .75*p32 + .25*p33;
x2 = x * x;
x3 = x2 * x;
y2 = y * y;
y3 = y2 * y;
% q = (a00 + a01 * y + a02 * y2 + a03 * y3) +...
% (a10 + a11 * y + a12 * y2 + a13 * y3) * x +...
% (a20 + a21 * y + a22 * y2 + a23 * y3) * x2 +...
% (a30 + a31 * y + a32 * y2 + a33 * y3) * x3;
q = (a00 + a01 * x + a02 * x2 + a03 * x3) +...
(a10 + a11 * x + a12 * x2 + a13 * x3) * y +...
(a20 + a21 * x + a22 * x2 + a23 * x3) * y2 +...
(a30 + a31 * x + a32 * x2 + a33 * x3) * y3;
Result:

how to find this function complexity?

I got log n but it's not log n it is log(log n) but why?
int function(int n){
return aux(n , 2)
}
int aux(int n, int x){
while (n<x) {
x *= x;
}
return x;
}
what is the complexity of function ?
Pretty sure the loop condition is supposed to be n > x so I'll be assuming it in this answer.
First, observe the values of x:
x1 = x0 * x0
= 2 * 2
= 2^2
x2 = x1 * x1
= x0 * x0 * x0 * x0
= 2 * 2 * 2 * 2
= 2^4
x3 = x2 * x2
= x1 * x1 * x1 * x1
= x0 * x0 * x0 * x0 * x0 * x0 * x0 * x0
= 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2
= 2^8
We see that the exponent is growing as 2^t where t is the number of iterations in the loop so we can obtain the closed form equation for x:
x = 2^(2^t)
Then we can solve for the number of iterations t:
n > x
=> n > 2^(2^t)
=> log(n) > 2^t
=> log(log(n)) > t
as required.

Find ratio/algorithm to translate different coordinate systems?

So I have two different coordinate systems, one is the incoming data and the other is how i plot points in the app. Is there a formula that, given some aligned up points, will give me an algorithm to calculate future points? Eg:
X = 6.5 & Y = 2 on one system is == X = 3101 & Y = 3441 in the other system.
Another set is 6.45/2.37 = 3211/3414. From these two matchups, how can I calculate a formula to "translate" one system into the other?
You need to solve two equations with two unknowns for X, and then the same for Y.
Let's go through this. First we do X:
3101 = 6.5 * a + b
3211 = 6.45 * a + b
First we isolate b:
3101 - 6.5 * a = b
3211 - 6.45 * a = b
Which gives:
3101 - 6.5 * a = 3211 - 6.45 * a
Now we can solve for a:
3101 - 6.5 * a - 3211 + 6.45 * a = 0
-110 -0.05 * a = 0
-110 = 0.05 * a
-2200 = a
Given this a we can solve for b using either of the original two equations:
3101 - 6.5 * a = b
3101 - 6.5 * -2200 = b
3101 + 14300 = b
17401 = b
b = 17401
So for X we have this formula:
X2 = -2200 * X1 + 17401
Let's try X1 = 6.5 and X1 = 6.45:
X2 = -2200 * 6.5 + 17401
X2 = -14300 + 17401
X2 = 3101
X2 = -2200 * 6.45 + 17401
X2 = -14190 + 17401
X2 = 3211
Doing the exact same math for Y gives me that the relationship follows this formula:
Y2 = Y1 * A + B
3441 = 2 * A + B 3414 = 2.37 * A + B
3441 - 2 * A = B 3414 - 2.37 * A = B
3441 - 2 * A = 3414 - 2.37 * A
3441 - 2 * A - 3414 + 2.37 * A = 0
27 + 0.37 * A = 0
0.37 * A = -27
0.37 * A = -27
A = -72.973
3441 = 2 * A + B
3441 = 2 * -72.973 + B
3441 - 2 * -72.973 = B
3441 + 145.946 = B
3586.946 = B
B = 3586.946
Which gives:
Y2 = Y1 * -72.973 + 3586.946
Let's test:
Y2 = 2 * -72.973 + 3586.946
Y2 = -145.946 + 3586.946
Y2 = 3441
Y2 = 2.37 * -72.973 + 3586.946
Y2 = -172.946 + 3586.946
Y2 = 3414
Your translation formulas are this:
X2 = X1 * -2200 + 17401
Y2 = Y1 * 72.973 + 3586.946
what you want is called linear interpolation, rule of three, etc

splitting trapezoid in given proportion

I need to split trapezoid in 2 part of given size with line, parallel basement. I need to get new h1 of new trapezoid.
For example I have trapezoid of area S and I want to split it in 2 trapezoids of areas S1 and S2.
S1 = aS; S2 = (1-a)S;
S1 = (a+z)*(h1)/2;
S2 = (b+z)*(1-h1)/2;
S1/S2 = KS;
To get new h1 I compare a and b, if a != b, I solve square equation and if a == b I work like with square. But sometimes I get mistakes because of rounding (for example when I solve this analytically I get a = b and program thinks a > b). How can I handle this? Or maybe there is another better way to split trapezoid?
Here is simplifyed code:
if (base > base_prev) {
b_t = base; // base of trapezoid
h = H; //height of trapezoid
a_t = base_prev; //another base of trapezoid
KS = S1 / S2;
a_x = (a_t - b_t) * (1 + KS) / h;
b_x = 2 * KS * b_t + 2 * b_t;
c_x = -(a_t * h + b_t * h);
h_tmp = (-b_x + sqrt(b_x * b_x - 4 * a_x * c_x)) / (2 * a_x);
if (h_tmp > h || h_tmp < 0)
h_tmp = (-b_x - sqrt(b_x * b_x - 4 * a_x * c_x)) / (2 * a_x);
} else if (base < base_prev) {
b_t = base_prev;
a_t = base;
KS = S1 / S2;
a_x = (a_t - b_t) * (1 + KS) / h;
b_x = 2 * KS * b_t + 2 * b_t;
c_x = -(a_t * h + b_t * h);
h_tmp = (-b_x + sqrt(b_x * b_x - 4 * a_x * c_x)) / (2 * a_x);
if (h_tmp > h || h_tmp < 0)
h_tmp = (-b_x - sqrt(b_x * b_x - 4 * a_x * c_x)) / (2 * a_x);
}
else {
KS = S1 / S2;
h_tmp = h * KS;
}
If you're dealing with catastrophic cancellation, one approach, dating back to a classic article by Forsythe, is to use the alternative solution form x = 2c/(-b -+ sqrt(b^2 - 4ac)) for the quadratic equation ax^2 + bx + c = 0. One way to write the two roots, good for b < 0, is
x = (-b + sqrt(b^2 - 4ac))/(2a)
x = 2c/(-b + sqrt(b^2 - 4ac)),
and another, good for b >= 0, is
x = 2c/(-b - sqrt(b^2 - 4ac))
x = (-b - sqrt(b^2 - 4ac))/(2a).
Alternatively, you could use the bisection method to obtain a reasonably good guess and polish it with Newton's method.

Resources