open-discussion >

**How to apply transformation matrix**Showing 1-8 of 8 posts

Dec 3, 2013 09:12 AM | Marc Lalancette

How to apply transformation matrix

Hello,

I'm starting to use GIFTI in a tool I'm writing and I didn't find anywhere a description of how the transformation matrix is to be applied to point coordinates. I assume it is meant to be like in NIFTI files, but I think it should be specified explicitly to avoid mistakes and thus incompatibilities between software. So if p is a column vector of (x, y, z, 1), and T is the transformation matrix, is it meant to be applied as:

A) T * p

as I suspect, or

B) p' * T

(p' being the transposed, row vector form of p) ?

Cheers,

Marc

I'm starting to use GIFTI in a tool I'm writing and I didn't find anywhere a description of how the transformation matrix is to be applied to point coordinates. I assume it is meant to be like in NIFTI files, but I think it should be specified explicitly to avoid mistakes and thus incompatibilities between software. So if p is a column vector of (x, y, z, 1), and T is the transformation matrix, is it meant to be applied as:

A) T * p

as I suspect, or

B) p' * T

(p' being the transposed, row vector form of p) ?

Cheers,

Marc

Dec 3, 2013 10:12 AM | John Harwell

RE: How to apply transformation matrix

From the GIFTI document:

2.8 MatrixData2.8.1 Description – Contains 16 text values representing a double- precision 4x4 transformation matrix. The values are listed as a one- dimensional array in row-major order which is used by most programming languages with the exception of FORTRAN and MATLAB. Note that OpenGL uses column-major order for its matrices.For example, the matrix below would appear as "m1 m2 m3 m4 m5 m6 m7 m8 m9 m10 m11 m12 m13 m14 m15 m16" is the MatrixData11 element.

m1 m2 m3 m4

m5 m6 m7 m8

m9 m10 m11 m12

m13 m14 m15 m16

Since the GIFTI transformation matrix is in row-major order, the translation values are in the bottom row (m13, m14, m15). I believe the NIFTI SFORM is column-major order (translation values are in the right-most column).

2.8 MatrixData2.8.1 Description – Contains 16 text values representing a double- precision 4x4 transformation matrix. The values are listed as a one- dimensional array in row-major order which is used by most programming languages with the exception of FORTRAN and MATLAB. Note that OpenGL uses column-major order for its matrices.For example, the matrix below would appear as "m1 m2 m3 m4 m5 m6 m7 m8 m9 m10 m11 m12 m13 m14 m15 m16" is the MatrixData11 element.

m1 m2 m3 m4

m5 m6 m7 m8

m9 m10 m11 m12

m13 m14 m15 m16

Since the GIFTI transformation matrix is in row-major order, the translation values are in the bottom row (m13, m14, m15). I believe the NIFTI SFORM is column-major order (translation values are in the right-most column).

Dec 3, 2013 11:12 AM | Marc Lalancette

RE: How to apply transformation matrix

Thanks John.

To confirm then, the correct transformation would be:

(x, y, z, 1) * T

which is not the same as with NIFTI sform.

Unless I'm missing something, row-major or column-major order only specifies how the data is stored (how to convert from a list to a 2d matrix). It does not imply anything about the meaning of the values in the matrix. And I didn't see any indication that (m13, m14, m15) were the translation values. So I really think this should be indicated in the documentation. I suspect I'm not the only one that would have assumed the "wrong way" of making the transformation.

Thanks again for your prompt reply!

Cheers

To confirm then, the correct transformation would be:

(x, y, z, 1) * T

which is not the same as with NIFTI sform.

Unless I'm missing something, row-major or column-major order only specifies how the data is stored (how to convert from a list to a 2d matrix). It does not imply anything about the meaning of the values in the matrix. And I didn't see any indication that (m13, m14, m15) were the translation values. So I really think this should be indicated in the documentation. I suspect I'm not the only one that would have assumed the "wrong way" of making the transformation.

Thanks again for your prompt reply!

Cheers

Dec 3, 2013 12:12 PM | John Harwell

RE: How to apply transformation matrix

OpenGL uses column-major order and an appendix in the OpenGL "Red
Book" (http://www.glprogramming.com/red/appendi...) shows the translation values in the right-most column.
Since the GIFTI spec indicates that the transformation matrix
data is in row-major order, the translation values must be in the
bottom row and hence values (m13, m14, m15).

I don't want to answer the pre- or post-multiply question. The best way is to create some data and test it.

I don't want to answer the pre- or post-multiply question. The best way is to create some data and test it.

Dec 3, 2013 03:12 PM | Marc Lalancette

RE: How to apply transformation matrix

Hmm... I'm getting more and more uncertain.

I think the meaningful object here is the matrix, not the storage order of elements. Thus if the OpenGL convention is to have the translation elements on the right of the matrix, and you want to follow that convention but with row-major order, shouldn't the translation elements not be in m13, 14, 15, but accordingly in m4, 8, 12? Then the transformation would be M * v (as in chapter 3 of that "red book"). But if you decided to have the convention of translation elements in 13, 14, 15, then the proper transformation would be M^T * v (or v^T * M).

Either way, the ambiguity seems a problem to me. If the GIFTI specification doesn't say, then different programs will decide to do it differently and thus be incompatible. As it stands, I'm still not sure.

You're right that if all I needed was to take GIFTI files created from a single other source, I could just try and figure out how they implemented it, but since I'm currently implementing my own, I have to decide how to encode and use this matrix. I could do it both ways and it would work. I just assumed that there would be a convention in the GIFTI format that I should follow.

I think the meaningful object here is the matrix, not the storage order of elements. Thus if the OpenGL convention is to have the translation elements on the right of the matrix, and you want to follow that convention but with row-major order, shouldn't the translation elements not be in m13, 14, 15, but accordingly in m4, 8, 12? Then the transformation would be M * v (as in chapter 3 of that "red book"). But if you decided to have the convention of translation elements in 13, 14, 15, then the proper transformation would be M^T * v (or v^T * M).

Either way, the ambiguity seems a problem to me. If the GIFTI specification doesn't say, then different programs will decide to do it differently and thus be incompatible. As it stands, I'm still not sure.

You're right that if all I needed was to take GIFTI files created from a single other source, I could just try and figure out how they implemented it, but since I'm currently implementing my own, I have to decide how to encode and use this matrix. I could do it both ways and it would work. I just assumed that there would be a convention in the GIFTI format that I should follow.

Dec 3, 2013 06:12 PM | Richard Reynolds

RE: How to apply transformation matrix

Hi Marc,

Transformation matrices T(x) are generally considered to

be applied as T*x, though there are some who prefer it

the other way. NIFTI (and therefore GIFTI) apply it in that

common way, as specified in the NIFTI standard.

The most detailed description of the NIFTI standard is in

the nifti1.h header file, here:

nifti.nimh.nih.gov

Search for either "Method 2" or "Method 3", though the

latter is more appropriate, as it applies directly to the stored

matrix, rather than one derived from a qform.

- rick

Transformation matrices T(x) are generally considered to

be applied as T*x, though there are some who prefer it

the other way. NIFTI (and therefore GIFTI) apply it in that

common way, as specified in the NIFTI standard.

The most detailed description of the NIFTI standard is in

the nifti1.h header file, here:

nifti.nimh.nih.gov

Search for either "Method 2" or "Method 3", though the

latter is more appropriate, as it applies directly to the stored

matrix, rather than one derived from a qform.

- rick

Dec 3, 2013 06:12 PM | Richard Reynolds

RE: How to apply transformation matrix

To be clear, GIFTI_Surface_Format.pdf does specify row-major

order, as is also used in NIFTI. That does not mean the offsets

are along the bottom row. The offsets are along the right column.

For an example, consider the FreeSurfer sample data, where the

matrix is not an identity. There the offsets are in the right column,

and the bottom row is 0, 0, 0, 1, as it should always be.

NIFTI and GIFTI use the same format, as they should.

- rick

order, as is also used in NIFTI. That does not mean the offsets

are along the bottom row. The offsets are along the right column.

For an example, consider the FreeSurfer sample data, where the

matrix is not an identity. There the offsets are in the right column,

and the bottom row is 0, 0, 0, 1, as it should always be.

NIFTI and GIFTI use the same format, as they should.

- rick

Dec 4, 2013 07:12 AM | Marc Lalancette

RE: How to apply transformation matrix

Thanks Richard. I'll go with that decisive statement. I
was familiar with the NIFTI documentation as I've been using it for
a few years. But I wanted confirmation that GIFTI was the
same given it wasn't stated in the documentation.

And given John's reply, maybe it's not as obvious as the developers might have thought.

Anyway, thanks for the help!

Cheers

And given John's reply, maybe it's not as obvious as the developers might have thought.

Anyway, thanks for the help!

Cheers