/// <summary>
        /// Build a texture coordinate transformation from the given parameters as specified in TextureTransform
        /// http://gun.teipir.gr/VRML-amgem/spec/part1/nodesRef.html#TextureTransform
        /// </summary>
        public static Trafo2d BuildVrmlTextureTrafo(V2d center, double rotation, V2d scale, V2d translation)
        {
            M33d C = M33d.Translation(center), Ci = M33d.Translation(-center);
            M33d R = M33d.Rotation(rotation), Ri = M33d.Rotation(-rotation);
            M33d S = M33d.Scale(scale), Si = M33d.Scale(1 / scale);
            M33d T = M33d.Translation(translation), Ti = M33d.Translation(-translation);

            return(new Trafo2d(
                       Ci * S * R * C * T,
                       Ti * Ci * Ri * Si * C));
        }
        public static void ConsistentWithMatrixScaleTest()
        {
            TrafoTesting.GenericTest(rnd =>
            {
                var scale = rnd.UniformV3d() * 10;
                var m     = M33d.Scale(scale);
                var r     = new Scale3d(scale);

                var p    = rnd.UniformV3d() * rnd.UniformInt(1000);
                var res  = m.Transform(p);
                var res2 = r.Transform(p);

                TrafoTesting.AreEqual(res, res2);
            });
        }
        /// <summary>
        /// Extracts texture transform from given node.
        /// </summary>
        public static Trafo2d ExtractVrmlTextureTrafo(this SymMapBase m)
        {
            if (m == null)
            {
                return(Trafo2d.Identity);
            }

            // get trafo parts
            var c = (V2d)m.Get <V2f>(Vrml97Sym.center, V2f.Zero);
            var r = (double)m.Get <float>(Vrml97Sym.rotation, 0.0f);
            var s = (V2d)m.Get <V2f>(Vrml97Sym.scale, new V2f(1, 1));
            var t = (V2d)m.Get <V2f>(Vrml97Sym.translation, V2f.Zero);

            M33d C = M33d.Translation(c), Ci = M33d.Translation(-c);
            M33d R = M33d.Rotation(r), Ri = M33d.Rotation(-r);
            M33d S = M33d.Scale(s), Si = M33d.Scale(1 / s);
            M33d T = M33d.Translation(t), Ti = M33d.Translation(-t);

            return(new Trafo2d(
                       Ci * S * R * C * T,
                       Ti * Ci * Ri * Si * C));
        }