How to get uv from ON_Xform matrix? (C++)

I need to read data from .3dm file.
The code I use to retrive uv:

const ON_Material* material = ON_Material::Cast(modelComponentIter);
ON_Texture texture = material->m_textures[0];
ON_Xform uvw = texture.m_uvw;

=====================

Values on UI (Rhino 6.22):


rotation 60
u: offset 2 repeat 1
v: offset 4 repeat 5

The value of uvw:
0.50000000000000011, -0.86602540378443860, 0.00000000000000000, 2.4641016151377544
4.3301270189221928, 2.5000000000000004, 0.00000000000000000, -18.660254037844389
0.00000000000000000, 0.00000000000000000, 1.0000000000000000, 0.00000000000000000
0.00000000000000000, 0.00000000000000000, 0.00000000000000000, 1.0000000000000000

Values extracted from the matrix above:
translation:
{X=2.46410155 Y=-18.6602535 Z=0.000000000 }
scale:
{X=4.35889912 Y=2.64575124 Z=1.00000000 }
rotation:
{Pitch=0.000000000 Yaw=46.6961861 Roll=0.000000000 }

==========================================
How can I get the correct values set on UI?

Here is some test data I collected:
The values extracted from the matrix are only correct when only one of offset/repeat/rotation is set.

===================================

rotation 0
u: repeat 1
v: repeat 5

0x000000ec1a2c8260 {1.00000000, 0.000000000, 0.000000000, 0.000000000}
0x000000ec1a2c8270 {0.000000000, 5.00000000, 0.000000000, 0.000000000}
0x000000ec1a2c8280 {0.000000000, 0.000000000, 1.00000000, 0.000000000}
0x000000ec1a2c8290 {0.000000000, 0.000000000, 0.000000000, 1.00000000}

scale:
{X=1.00000000 Y=5.00000000 Z=1.00000000 }

======================================
rotation 60
u: repeat 1
v: repeat 1

0x000000ec1a2c8260 {0.500000000, 0.866025388, 0.000000000, 0.000000000}
0x000000ec1a2c8270 {-0.866025388, 0.500000000, 0.000000000, 0.000000000}
0x000000ec1a2c8280 {0.000000000, 0.000000000, 1.00000000, 0.000000000}
0x000000ec1a2c8290 {0.000000000, 0.000000000, 0.000000000, 1.00000000}

roration:
{Pitch=0.000000000 Yaw=59.9999847 Roll=0.000000000 }

======================================
rotation 60
u: repeat 1
v: repeat 5

0x000000ec1a2c8260 {0.500000000, 4.33012724, 0.000000000, 0.000000000}
0x000000ec1a2c8270 {-0.866025388, 2.50000000, 0.000000000, 0.000000000}
0x000000ec1a2c8280 {0.000000000, 0.000000000, 1.00000000, 0.000000000}
0x000000ec1a2c8290 {0.000000000, 0.000000000, 0.000000000, 1.00000000}

scale:
{X=4.35889912 Y=2.64575124 Z=1.00000000 }
rotation:
{Pitch=0.000000000 Yaw=46.6961861 Roll=0.000000000 }

======================================
rotation 0
u: offset 2 repeat 1
v: offset 4 repeat 1

0x000000ec1a2c8400 {1.0000000000000000, 0.00000000000000000, 0.00000000000000000, -2.0000000000000000}
0x000000ec1a2c8420 {0.00000000000000000, 1.0000000000000000, 0.00000000000000000, -4.0000000000000000}
0x000000ec1a2c8440 {0.00000000000000000, 0.00000000000000000, 1.0000000000000000, 0.00000000000000000}
0x000000ec1a2c8460 {0.00000000000000000, 0.00000000000000000, 0.00000000000000000, 1.0000000000000000}

translation:
{X=-2.00000000 Y=-4.00000000 Z=0.000000000 }
scale:
{X=1.00000000 Y=1.00000000 Z=1.00000000 }

======================================
rotation 60
u: offset 2 repeat 1
v: offset 4 repeat 1

0x000000ec1a2c8400 {0.50000000000000011, -0.86602540378443860, 0.00000000000000000, 2.4641016151377544}
0x000000ec1a2c8420 {0.86602540378443860, 0.50000000000000011, 0.00000000000000000, -3.7320508075688776}
0x000000ec1a2c8440 {0.00000000000000000, 0.00000000000000000, 1.0000000000000000, 0.00000000000000000}
0x000000ec1a2c8460 {0.00000000000000000, 0.00000000000000000, 0.00000000000000000, 1.0000000000000000}

translation:
{X=2.46410155 Y=-3.73205090 Z=0.000000000 }
rotation:
{Pitch=0.000000000 Yaw=59.9999847 Roll=0.000000000 }

======================================
rotation 60
u: offset 2 repeat 1
v: offset 4 repeat 5

0.50000000000000011, -0.86602540378443860, 0.00000000000000000, 2.4641016151377544}
4.3301270189221928, 2.5000000000000004, 0.00000000000000000, -18.660254037844389}
0.00000000000000000, 0.00000000000000000, 1.0000000000000000, 0.00000000000000000}
0.00000000000000000, 0.00000000000000000, 0.00000000000000000, 1.0000000000000000}

translation:
{X=2.46410155 Y=-18.6602535 Z=0.000000000 }
scale:
{X=4.35889912 Y=2.64575124 Z=1.00000000 }
rotation:
{Pitch=0.000000000 Yaw=46.6961861 Roll=0.000000000 }

You will have to use the RDK functionality to get at this data reliably…and it looks like you are using OpenNURBS rather than Rhino.

Otherwise, you’ll have to use some kind of xform decomposition function. Something like this:

void ConstructXform( double dScaleX, double dScaleY, double dScaleZ,

double dAngleX, double dAngleY, double dAngleZ,

double dTransX, double dTransY, double dTransZ, ON_Xform& xform)

{

//Construct new transformation xform

ON_Xform xformTranslation = ON_Xform::TranslationTransformation(dTransX, dTransY, dTransZ);

ON_Xform xformRotationX(1);

xformRotationX.Rotation(DegreesToRadians(dAngleX), ON_xaxis, ON_origin);

ON_Xform xformRotationY(1);

xformRotationY.Rotation(DegreesToRadians(dAngleY), ON_yaxis, ON_origin);

ON_Xform xformRotationZ(1);

xformRotationZ.Rotation(DegreesToRadians(dAngleZ), ON_zaxis, ON_origin);

ON_Xform xformRotation(1);

xformRotation = xformRotationZ * xformRotationY * xformRotationX;

ON_Xform xformScaling = ON_Xform::DiagonalTransformation(dScaleX, dScaleY, dScaleZ);

ON_Xform xformTransformation(1);

xformTransformation = xformTranslation * xformRotation * xformScaling;

xform = xformTransformation;

}

void DeconstructXform(const ON_Xform& xformIn,
double& dScaleX, double& dScaleY, double& dScaleZ,
double& dAngleX, double& dAngleY, double& dAngleZ,
double& dTransX, double& dTransY, double& dTransZ)
{
// Returns all angles in degrees.

ON_Xform xform = xformIn;

dScaleX = sqrt(xform[0][0] * xform[0][0] + xform[0][1] * xform[0][1] + xform[0][2] * xform[0][2]);
dScaleY = sqrt(xform[1][0] * xform[1][0] + xform[1][1] * xform[1][1] + xform[1][2] * xform[1][2]);
dScaleZ = sqrt(xform[2][0] * xform[2][0] + xform[2][1] * xform[2][1] + xform[2][2] * xform[2][2]);

ON_Xform S;
ConstructXform(dScaleX, dScaleY, dScaleZ, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, S);
S.Invert();

xform = S * xform;

const double dSinBeta = -xform[2][0];

double dCosBeta = sqrt(1.0 - dSinBeta * dSinBeta);
if (dCosBeta < 0.0)
{
	dCosBeta = -dCosBeta;
}

double dSinAlpha, dCosAlpha, dSinGamma, dCosGamma;

if (dCosBeta < 1e-6)
{
	dSinAlpha = -xform[1][2];
	dCosAlpha =  xform[1][1];
	dSinGamma = 0.0;
	dCosGamma = 1.0;
}
else
{
	dSinAlpha = xform[2][1] / dCosBeta;
	dCosAlpha = xform[2][2] / dCosBeta;
	dSinGamma = xform[1][0] / dCosBeta;
	dCosGamma = xform[0][0] / dCosBeta;
}

dAngleX = (RadiansToDegrees(atan2(dSinAlpha, dCosAlpha)));
dAngleY = (RadiansToDegrees(atan2(dSinBeta,  dCosBeta )));
dAngleZ = (RadiansToDegrees(atan2(dSinGamma, dCosGamma)));

ON_Xform R;
ConstructXform(dScaleX, dScaleY, dScaleZ, dAngleX, dAngleY, dAngleZ, 0.0, 0.0, 0.0, R);
R.Invert();

ON_Xform T = R * xformIn;

dTransX = -T[0][3];
dTransY = -T[1][3];
dTransZ = -T[2][3];

}

Thanks Andrew. I decompose xform by the code listed below:

float offset_u = (uvw[0][3] - uvw[0][1] * (
(uvw[1][3] * uvw[0][0] - uvw[1][0] * uvw[0][3]) / (uvw[1][1] * uvw[0][0] - uvw[1][0] * uvw[0][1])
)) / uvw[0][0];
float offset_v = (uvw[1][3] * uvw[0][0] - uvw[1][0] * uvw[0][3]) / (uvw[1][1] * uvw[0][0] - uvw[1][0] * uvw[0][1]);
float repeat_u = Sqrt(uvw[0][0] * uvw[0][0] + uvw[0][1] * uvw[0][1]);
float repeat_v = Sqrt(uvw[1][0] * uvw[1][0] + uvw[1][1] * uvw[1][1]);
float rotation = Acos(uvw[0][0] / repeat_u);