shinzou
shinzou

Reputation: 6192

Transform a 3X3 transform matrix to 4X4 matrix for css transform matrix3d

I have a 3X3 transform matrix that's the output of a homography transform.

I want to rotate and stretch a div according to this matrix but it looks like css transform either receives a 4X4 matrix or a 2X3 matrix.

I tried to convert the 3X3 matrix by adding zeros and a one like here but it looks completley wrong (it's either making the div rotated by 90 degrees or if I do a transpose, too small).

How can I transform that 3X3 matrix such that css' transform will work correctly?

Upvotes: 3

Views: 2989

Answers (1)

Bellian
Bellian

Reputation: 2140

Here some thougths that will propably help you:

There are a few possibilities concerning the matrix you recive:


The matrix is a 2D transformation matrix: In this case the matrix extension you do wil fail, because the matrix layout will look like this:

[x1, x2, tx]
[y1, y2, ty]
[0 , 0 , 1 ]

An extension would then look like this for a 4x4 matrix assuming that X and Y-axis dont change:

[x1, x2, 0, tx]
[y1, y2, 0, ty]
[0 , 0 , 1, 0 ]
[0 , 0 , 0, 1 ]

But since css is using a 2x3 matrix the last row is implied. So you can add them like this: transform: matrix(x1,y1,x2,y2,tx,ty); (see https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix)


The matrix is a 3D rotation matrix: In this case the matrix extension you do wil fail, because the matrix layout will look like this:

[x1, x2, x3]
[y1, y2, y3]
[z1, z2, z3]

An extension would then look like this for a 4x4 matrix: (see the link in your question)

[x1, x2, x3, 0]
[y1, y2, y3, 0]
[z3, z3, z3, 0]
[0 , 0 , 0 , 1]

You can add them like this: transform: matrix(x1,y1,z1,0, x2,y2,z2,0, x3,y3,z3,0, 0,0,0,1); (see https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix)


Last possibility: the Matrix is a projective one. No clue hot to handle this..


If i had to take a guess: By looking at this example (from the link you provided) I would say this is a 2D transformation matrix

BE AWARE: the jsfeat lib has a row-major order, but css needs a column-major order!

var affine_kernel = new jsfeat.motion_model.affine2d();
var affine_transform = new jsfeat.matrix_t(3, 3, jsfeat.F32_t | jsfeat.C1_t);

var count = 33;
var from = [];
var to = [];
 
for(var i = 0; i < count; ++i) {
    from[i] = { "x":Math.random()*320, "y":Math.random()*240 };
    to[i] = { "x":from[i].x + 5, "y":from[i].y+5 };
}
affine_kernel.run(from, to, affine_transform, count);

var a = [...affine_transform.data.subarray(0 , 6)];
b = [
  0.08420821279287338,
  -0.03247755020856857,
  14.28314018249511,
  -0.009080140851438,
  0.11894367635250,
  7.15110540390014,
  -0.00034110905835,
  -0.01147077046,
  1
];

window.addEventListener('load', function(){
  var elem = document.getElementById('to-transform');
  elem.style.transform = 'matrix('+a[0]+','+a[3]+','+a[1]+','+a[4]+','+a[2]+','+a[5]+')';
  
  var mat = [b[0],b[3],0,b[6], b[1],b[4],0,b[7], 0,0,1,0, b[2],b[5],0,b[8] ]
  var elem1 = document.getElementById('to-transform2');
  elem1.style.transform = 'matrix3d('+mat.join(',')+')';
})
.container {
  width:200px;
  height:200px;
  
  background: #aaa;
  position:relative;
  float:left;
  margin-right:10px;
}

.to-transform {
  width:100px;
  height:100px;
  position:absolute;
  
  background: #a00;
  text-align: center;
  line-height: 92px;
}
<script type="text/javascript" src="https://inspirit.github.io/jsfeat/js/jsfeat-min.js"></script>

<div class="container">
  <div id="to-transform" class="to-transform">to-transform</div>
</div>
<div class="container">
  <div id="to-transform2" class="to-transform">to-transform2</div>
</div>

Upvotes: 2

Related Questions