Interleave rows of single matrix

Alec Jacobson

July 18, 2014

weblog/

Dealing with xyz coordinates in linear algebra for computer graphics, there are predominant two styles when concatenating a list of many positions/vectors/matrices. The first groups common coordinates together. For example a list of mesh vertex coordinates may look like:

V = [x1
     x2
     ...
     xk
     y1
     y2
     ...
     yk
     z1
     z2
     ...
     zk];

The other style groups common objects together, listing all coordinates in a stream. For our vertex positions this would look like:

V = [x1
     y1
     z1
     x2
     y2
     z2
     ...
     xk
     yk
     zk];

In OpenGL and array language the first option has a data access stride of 1 if pulling x-coordinates and the second option has a stride of n. Of course if pulling position vectors then the first option has a stride of n and the second a stride of 1. Hence, the two styles really have appropriate use cases depending on data access patterns.

This gets a bit more complicated if we're not just storing a scalar in each row, but a n-vector.

In matlab, it's very easy to convert between one representation and the other. Suppose you have a k*m-by-n matrix A stored in the first format above. We can rearrange it to move all common objects together (forming a stack of k m-by-n matrices), with:

A = [1 2 3; ...
     4 5 6; ...
     7 8 9; ...
    10 11 12; ...
    13 14 15; ...
    16 17 18; ...
    19 20 21; ...
    22 23 24];
n = 3;
B = reshape(permute(reshape(A,[],2,n),[3 2 1]),n,[])';

and the output is

B =

 1     2     3
13    14    15
 4     5     6
16    17    18
 7     8     9
19    20    21
10    11    12
22    23    24

To convert back:

C = reshape(permute(reshape(B',n,2,[]),[3 2 1]),[],n);

and we get again:

C =
 1     2     3
 4     5     6
 7     8     9
10    11    12
13    14    15
16    17    18
19    20    21
22    23    24