Blame ImathTest/testProcrustes.cpp

Packit 8dc392
///////////////////////////////////////////////////////////////////////////
Packit 8dc392
//
Packit 8dc392
// Copyright (c) 2010, Industrial Light & Magic, a division of Lucas
Packit 8dc392
// Digital Ltd. LLC
Packit 8dc392
// 
Packit 8dc392
// All rights reserved.
Packit 8dc392
// 
Packit 8dc392
// Redistribution and use in source and binary forms, with or without
Packit 8dc392
// modification, are permitted provided that the following conditions are
Packit 8dc392
// met:
Packit 8dc392
// *       Redistributions of source code must retain the above copyright
Packit 8dc392
// notice, this list of conditions and the following disclaimer.
Packit 8dc392
// *       Redistributions in binary form must reproduce the above
Packit 8dc392
// copyright notice, this list of conditions and the following disclaimer
Packit 8dc392
// in the documentation and/or other materials provided with the
Packit 8dc392
// distribution.
Packit 8dc392
// *       Neither the name of Industrial Light & Magic nor the names of
Packit 8dc392
// its contributors may be used to endorse or promote products derived
Packit 8dc392
// from this software without specific prior written permission. 
Packit 8dc392
// 
Packit 8dc392
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 8dc392
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 8dc392
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 8dc392
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 8dc392
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 8dc392
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 8dc392
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 8dc392
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 8dc392
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 8dc392
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 8dc392
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 8dc392
//
Packit 8dc392
///////////////////////////////////////////////////////////////////////////
Packit 8dc392
Packit 8dc392
#include "ImathMatrixAlgo.h"
Packit 8dc392
#include "ImathRandom.h"
Packit 8dc392
#include "ImathEuler.h"
Packit 8dc392
#include <iostream>
Packit 8dc392
#include <assert.h>
Packit 8dc392
#include <cmath>
Packit 8dc392
#include <vector>
Packit 8dc392
#include <limits>
Packit 8dc392
Packit 8dc392
// Verify that if our transformation is already orthogonal, procrustes doesn't
Packit 8dc392
// change that:
Packit 8dc392
template <typename T>
Packit 8dc392
void
Packit 8dc392
testTranslationRotationMatrix (const IMATH_INTERNAL_NAMESPACE::M44d& mat)
Packit 8dc392
{
Packit 8dc392
    std::cout << "Testing known translate/rotate matrix:\n " << mat;
Packit 8dc392
    typedef IMATH_INTERNAL_NAMESPACE::Vec3<T> Vec;
Packit 8dc392
Packit 8dc392
    static IMATH_INTERNAL_NAMESPACE::Rand48 rand (2047);
Packit 8dc392
Packit 8dc392
    size_t numPoints = 7;
Packit 8dc392
    std::vector<Vec> from;  from.reserve (numPoints);
Packit 8dc392
    std::vector<Vec> to;    to.reserve (numPoints);
Packit 8dc392
    for (size_t i = 0; i < numPoints; ++i)
Packit 8dc392
    {
Packit 8dc392
        IMATH_INTERNAL_NAMESPACE::V3d a (rand.nextf(), rand.nextf(), rand.nextf());
Packit 8dc392
        IMATH_INTERNAL_NAMESPACE::V3d b = a * mat;
Packit 8dc392
Packit 8dc392
        from.push_back (Vec(a));
Packit 8dc392
        to.push_back (Vec(b));
Packit 8dc392
    }
Packit 8dc392
Packit 8dc392
    std::vector<T> weights (numPoints, T(1));
Packit 8dc392
    const IMATH_INTERNAL_NAMESPACE::M44d m1 = procrustesRotationAndTranslation (&from[0], &to[0], &weights[0], numPoints);
Packit 8dc392
    const IMATH_INTERNAL_NAMESPACE::M44d m2 = procrustesRotationAndTranslation (&from[0], &to[0], numPoints);
Packit 8dc392
Packit 8dc392
    const T eps = sizeof(T) == 8 ? 1e-8 : 1e-4;
Packit 8dc392
    for (size_t i = 0; i < numPoints; ++i)
Packit 8dc392
    {
Packit 8dc392
        const IMATH_INTERNAL_NAMESPACE::V3d a = from[i];
Packit 8dc392
        const IMATH_INTERNAL_NAMESPACE::V3d b = to[i];
Packit 8dc392
        const IMATH_INTERNAL_NAMESPACE::V3d b1 = a * m1;
Packit 8dc392
        const IMATH_INTERNAL_NAMESPACE::V3d b2 = a * m2;
Packit 8dc392
Packit 8dc392
        assert ((b - b1).length() < eps);
Packit 8dc392
        assert ((b - b2).length() < eps);
Packit 8dc392
    }
Packit 8dc392
    std::cout << "  OK\n";
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
// Test that if we pass in a matrix that we know consists only of translates,
Packit 8dc392
// rotates, and uniform scale that we get an exact match.
Packit 8dc392
template <typename T>
Packit 8dc392
void testWithTranslateRotateAndScale (const IMATH_INTERNAL_NAMESPACE::M44d& m)
Packit 8dc392
{
Packit 8dc392
    std::cout << "Testing with known translate/rotate/scale matrix\n" << m;
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::Rand48 rand(5376);
Packit 8dc392
Packit 8dc392
    typedef IMATH_INTERNAL_NAMESPACE::Vec3<T> V3;
Packit 8dc392
    std::vector<V3> from;
Packit 8dc392
    std::vector<T> weights;
Packit 8dc392
Packit 8dc392
    const float eps = 1e-4;
Packit 8dc392
    std::cout << "numPoints: " << std::flush;
Packit 8dc392
    for (size_t numPoints = 1; numPoints < 10; ++numPoints)
Packit 8dc392
    {
Packit 8dc392
        from.push_back (V3(rand.nextf(), rand.nextf(), rand.nextf()));
Packit 8dc392
        weights.push_back (rand.nextf());
Packit 8dc392
        std::cout << from.size() << " ";
Packit 8dc392
Packit 8dc392
        std::vector<V3> to;
Packit 8dc392
        for (size_t i = 0; i < from.size(); ++i)
Packit 8dc392
            to.push_back (from[i] * m);
Packit 8dc392
Packit 8dc392
        // weighted:
Packit 8dc392
        IMATH_INTERNAL_NAMESPACE::M44d res = IMATH_INTERNAL_NAMESPACE::procrustesRotationAndTranslation (&from[0], &to[0], &weights[0], from.size(), true);
Packit 8dc392
        for (size_t i = 0; i < from.size(); ++i)
Packit 8dc392
            assert ((from[i] * res - to[i]).length() < eps);
Packit 8dc392
Packit 8dc392
        // unweighted:
Packit 8dc392
        res = IMATH_INTERNAL_NAMESPACE::procrustesRotationAndTranslation (&from[0], &to[0], from.size(), true);
Packit 8dc392
        for (size_t i = 0; i < from.size(); ++i)
Packit 8dc392
            assert ((from[i] * res - to[i]).length() < eps);
Packit 8dc392
    }
Packit 8dc392
    std::cout << "  OK\n";
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
template <typename T>
Packit 8dc392
double
Packit 8dc392
procrustesError (const IMATH_INTERNAL_NAMESPACE::Vec3<T>* from,
Packit 8dc392
                 const IMATH_INTERNAL_NAMESPACE::Vec3<T>* to,
Packit 8dc392
                 const T* weights,
Packit 8dc392
                 const size_t n,
Packit 8dc392
                 const IMATH_INTERNAL_NAMESPACE::M44d& xform)
Packit 8dc392
{
Packit 8dc392
    double result = 0.0;
Packit 8dc392
    double residual = 0.0;
Packit 8dc392
    for (size_t i = 0; i < n; ++i)
Packit 8dc392
    {
Packit 8dc392
        IMATH_INTERNAL_NAMESPACE::V3d xformed = IMATH_INTERNAL_NAMESPACE::V3d(from[i]) * xform;
Packit 8dc392
        IMATH_INTERNAL_NAMESPACE::V3d diff = xformed - IMATH_INTERNAL_NAMESPACE::V3d(to[i]);
Packit 8dc392
        const double w = weights[i];
Packit 8dc392
        const double mag = w * diff.length2();
Packit 8dc392
Packit 8dc392
        // Use Kahan summation for the heck of it:
Packit 8dc392
        const double y = mag - residual;
Packit 8dc392
        const double t = result + y;
Packit 8dc392
        residual = (t - result) - y;
Packit 8dc392
        result = t;
Packit 8dc392
    }
Packit 8dc392
    return result;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
template <typename T>
Packit 8dc392
void
Packit 8dc392
verifyProcrustes (const std::vector<IMATH_INTERNAL_NAMESPACE::Vec3<T> >& from, 
Packit 8dc392
                  const std::vector<IMATH_INTERNAL_NAMESPACE::Vec3<T> >& to)
Packit 8dc392
{
Packit 8dc392
    typedef IMATH_INTERNAL_NAMESPACE::Vec3<T> V3;
Packit 8dc392
Packit 8dc392
    const T eps = std::sqrt(std::numeric_limits<T>::epsilon());
Packit 8dc392
Packit 8dc392
    const size_t n = from.size();
Packit 8dc392
Packit 8dc392
    // Validate that passing in uniform weights gives the same answer as
Packit 8dc392
    // passing in no weights:
Packit 8dc392
    std::vector<T> weights (from.size());
Packit 8dc392
    for (size_t i = 0; i < weights.size(); ++i)
Packit 8dc392
        weights[i] = 1;
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::M44d m1 = procrustesRotationAndTranslation (&from[0], &to[0], n);
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::M44d m2 = procrustesRotationAndTranslation (&from[0], &to[0], &weights[0], n);
Packit 8dc392
    for (int i = 0; i < 4; ++i)
Packit 8dc392
        for (int j = 0; j < 4; ++j)
Packit 8dc392
            assert (std::abs(m1[i][j] - m2[i][j]) < eps);
Packit 8dc392
Packit 8dc392
    // Now try the weighted version:
Packit 8dc392
    for (size_t i = 0; i < weights.size(); ++i)
Packit 8dc392
        weights[i] = i+1;
Packit 8dc392
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::M44d m = procrustesRotationAndTranslation (&from[0], &to[0], &weights[0], n);
Packit 8dc392
Packit 8dc392
    // with scale:
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::M44d ms = procrustesRotationAndTranslation (&from[0], &to[0], &weights[0], n, true);
Packit 8dc392
Packit 8dc392
    // Verify that it's orthonormal w/ positive determinant.
Packit 8dc392
    const T det = m.determinant();
Packit 8dc392
    assert (std::abs(det - T(1)) < eps);
Packit 8dc392
Packit 8dc392
    // Verify orthonormal:
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::M33d upperLeft;
Packit 8dc392
    for (int i = 0; i < 3; ++i)
Packit 8dc392
        for (int j = 0; j < 3; ++j)
Packit 8dc392
            upperLeft[i][j] = m[i][j];
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::M33d product = upperLeft * upperLeft.transposed();
Packit 8dc392
    for (int i = 0; i < 3; ++i)
Packit 8dc392
    {
Packit 8dc392
        for (int j = 0; j < 3; ++j)
Packit 8dc392
        {
Packit 8dc392
            const double expected = (i == j ? 1.0 : 0.0);
Packit 8dc392
            assert (std::abs(product[i][j] - expected) < eps);
Packit 8dc392
        }
Packit 8dc392
    }
Packit 8dc392
Packit 8dc392
    // Verify that nearby transforms are worse:
Packit 8dc392
    const size_t numTries = 10;
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::Rand48 rand (1056);
Packit 8dc392
    const double delta = 1e-3;
Packit 8dc392
    for (size_t i = 0; i < numTries; ++i)
Packit 8dc392
    {
Packit 8dc392
        // Construct an orthogonal rotation matrix using Euler angles:
Packit 8dc392
        IMATH_INTERNAL_NAMESPACE::Eulerd diffRot (delta * rand.nextf(), delta * rand.nextf(), delta * rand.nextf());
Packit 8dc392
 
Packit 8dc392
        assert (procrustesError (&from[0], &to[0], &weights[0], n, m * diffRot.toMatrix44()) >
Packit 8dc392
                procrustesError (&from[0], &to[0], &weights[0], n, m));
Packit 8dc392
Packit 8dc392
        // Try a small translation:
Packit 8dc392
        IMATH_INTERNAL_NAMESPACE::V3d diffTrans (delta * rand.nextf(), delta * rand.nextf(), delta * rand.nextf());
Packit 8dc392
        IMATH_INTERNAL_NAMESPACE::M44d translateMatrix;
Packit 8dc392
        translateMatrix.translate (diffTrans);
Packit 8dc392
        assert (procrustesError (&from[0], &to[0], &weights[0], n, m * translateMatrix) >
Packit 8dc392
                procrustesError (&from[0], &to[0], &weights[0], n, m));
Packit 8dc392
    }
Packit 8dc392
Packit 8dc392
    // Try a small scale:
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::M44d newMat = ms;
Packit 8dc392
    const double scaleDiff = delta;
Packit 8dc392
    for (size_t i = 0; i < 3; ++i)
Packit 8dc392
        for (size_t j = 0; j < 3; ++j)
Packit 8dc392
            newMat[i][j] = ms[i][j] * (1.0 + scaleDiff);
Packit 8dc392
    assert (procrustesError (&from[0], &to[0], &weights[0], n, newMat) >
Packit 8dc392
            procrustesError (&from[0], &to[0], &weights[0], n, ms));
Packit 8dc392
Packit 8dc392
    for (size_t i = 0; i < 3; ++i)
Packit 8dc392
        for (size_t j = 0; j < 3; ++j)
Packit 8dc392
            newMat[i][j] = ms[i][j] * (1.0 - scaleDiff);
Packit 8dc392
    assert (procrustesError (&from[0], &to[0], &weights[0], n, newMat) >
Packit 8dc392
            procrustesError (&from[0], &to[0], &weights[0], n, ms));
Packit 8dc392
Packit 8dc392
    //
Packit 8dc392
    // Verify the magical property that makes shape springs work:
Packit 8dc392
    // when the displacements Q*A-B, times the weights,
Packit 8dc392
    // are applied as forces at B,
Packit 8dc392
    // there is zero net force and zero net torque.
Packit 8dc392
    //
Packit 8dc392
    {
Packit 8dc392
        IMATH_INTERNAL_NAMESPACE::V3d center (0, 0, 0);
Packit 8dc392
Packit 8dc392
        IMATH_INTERNAL_NAMESPACE::V3d netForce(0);
Packit 8dc392
        IMATH_INTERNAL_NAMESPACE::V3d netTorque(0);
Packit 8dc392
        for (int iPoint = 0; iPoint < n; ++iPoint)
Packit 8dc392
        {
Packit 8dc392
            const IMATH_INTERNAL_NAMESPACE::V3d force = weights[iPoint] * (from[iPoint]*m - to[iPoint]);
Packit 8dc392
            netForce += force;
Packit 8dc392
            netTorque += to[iPoint].cross (force);
Packit 8dc392
        }
Packit 8dc392
Packit 8dc392
        assert (netForce.length2() < eps);
Packit 8dc392
        assert (netTorque.length2() < eps);
Packit 8dc392
    }
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
template <typename T>
Packit 8dc392
void
Packit 8dc392
testProcrustesWithMatrix (const IMATH_INTERNAL_NAMESPACE::M44d& m)
Packit 8dc392
{
Packit 8dc392
    std::cout << "Testing Procrustes algorithm with arbitrary matrix: \n" << m;
Packit 8dc392
    std::vector<IMATH_INTERNAL_NAMESPACE::Vec3<T> > fromPoints;
Packit 8dc392
    std::vector<IMATH_INTERNAL_NAMESPACE::Vec3<T> > toPoints;
Packit 8dc392
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::Rand48 random (1209);
Packit 8dc392
    std::cout << "   numPoints: ";
Packit 8dc392
    for (size_t numPoints = 1; numPoints < 10; ++numPoints)
Packit 8dc392
    {
Packit 8dc392
        std::cout << numPoints << " " << std::flush;
Packit 8dc392
        fromPoints.clear(); toPoints.clear();
Packit 8dc392
        for (size_t i = 0; i < numPoints; ++i)
Packit 8dc392
        {
Packit 8dc392
            const IMATH_INTERNAL_NAMESPACE::V3d fromPt (random.nextf(), random.nextf(), random.nextf());
Packit 8dc392
            const IMATH_INTERNAL_NAMESPACE::V3d toPt = fromPt * m;
Packit 8dc392
            fromPoints.push_back (IMATH_INTERNAL_NAMESPACE::Vec3<T>(fromPt));
Packit 8dc392
            toPoints.push_back (IMATH_INTERNAL_NAMESPACE::Vec3<T>(toPt));
Packit 8dc392
        }
Packit 8dc392
        verifyProcrustes (fromPoints, toPoints);
Packit 8dc392
    }
Packit 8dc392
    std::cout << "OK\n";
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
template <typename T>
Packit 8dc392
void
Packit 8dc392
testProcrustesImp ()
Packit 8dc392
{
Packit 8dc392
    // Test the empty case:
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::M44d id = 
Packit 8dc392
        procrustesRotationAndTranslation ((IMATH_INTERNAL_NAMESPACE::Vec3<T>*) 0, 
Packit 8dc392
                                          (IMATH_INTERNAL_NAMESPACE::Vec3<T>*) 0,
Packit 8dc392
                                          (T*) 0,
Packit 8dc392
                                          0);
Packit 8dc392
    assert (id == IMATH_INTERNAL_NAMESPACE::M44d());
Packit 8dc392
Packit 8dc392
    id = procrustesRotationAndTranslation ((IMATH_INTERNAL_NAMESPACE::Vec3<T>*) 0, 
Packit 8dc392
                                           (IMATH_INTERNAL_NAMESPACE::Vec3<T>*) 0,
Packit 8dc392
                                           0);
Packit 8dc392
    assert (id == IMATH_INTERNAL_NAMESPACE::M44d());
Packit 8dc392
Packit 8dc392
    // First we'll test with a bunch of known translation/rotation matrices
Packit 8dc392
    // to make sure we get back exactly the same points:
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::M44d m;
Packit 8dc392
    m.makeIdentity();
Packit 8dc392
    testTranslationRotationMatrix<T> (m);
Packit 8dc392
Packit 8dc392
    m.translate (IMATH_INTERNAL_NAMESPACE::V3d(3.0, 5.0, -0.2));
Packit 8dc392
    testTranslationRotationMatrix<T> (m);
Packit 8dc392
Packit 8dc392
    m.rotate (IMATH_INTERNAL_NAMESPACE::V3d(M_PI, 0, 0));
Packit 8dc392
    testTranslationRotationMatrix<T> (m);
Packit 8dc392
    
Packit 8dc392
    m.rotate (IMATH_INTERNAL_NAMESPACE::V3d(0, M_PI/4.0, 0));
Packit 8dc392
    testTranslationRotationMatrix<T> (m);
Packit 8dc392
Packit 8dc392
    m.rotate (IMATH_INTERNAL_NAMESPACE::V3d(0, 0, -3.0/4.0 * M_PI));
Packit 8dc392
    testTranslationRotationMatrix<T> (m);
Packit 8dc392
Packit 8dc392
    m.makeIdentity();
Packit 8dc392
    testWithTranslateRotateAndScale<T> (m);
Packit 8dc392
Packit 8dc392
    m.translate (IMATH_INTERNAL_NAMESPACE::V3d(0.4, 6.0, 10.0));
Packit 8dc392
    testWithTranslateRotateAndScale<T> (m);
Packit 8dc392
Packit 8dc392
    m.rotate (IMATH_INTERNAL_NAMESPACE::V3d(M_PI, 0, 0));
Packit 8dc392
    testWithTranslateRotateAndScale<T> (m);
Packit 8dc392
Packit 8dc392
    m.rotate (IMATH_INTERNAL_NAMESPACE::V3d(0, M_PI/4.0, 0));
Packit 8dc392
    testWithTranslateRotateAndScale<T> (m);
Packit 8dc392
Packit 8dc392
    m.rotate (IMATH_INTERNAL_NAMESPACE::V3d(0, 0, -3.0/4.0 * M_PI));
Packit 8dc392
    testWithTranslateRotateAndScale<T> (m);
Packit 8dc392
Packit 8dc392
    m.scale (IMATH_INTERNAL_NAMESPACE::V3d(2.0, 2.0, 2.0));
Packit 8dc392
    testWithTranslateRotateAndScale<T> (m);
Packit 8dc392
Packit 8dc392
    m.scale (IMATH_INTERNAL_NAMESPACE::V3d(0.01, 0.01, 0.01));
Packit 8dc392
    testWithTranslateRotateAndScale<T> (m);
Packit 8dc392
Packit 8dc392
    // Now we'll test with some random point sets and verify
Packit 8dc392
    // the various Procrustes properties:
Packit 8dc392
    std::vector<IMATH_INTERNAL_NAMESPACE::Vec3<T> > fromPoints;
Packit 8dc392
    std::vector<IMATH_INTERNAL_NAMESPACE::Vec3<T> > toPoints;
Packit 8dc392
    fromPoints.clear(); toPoints.clear();
Packit 8dc392
Packit 8dc392
    for (size_t i = 0; i < 4; ++i)
Packit 8dc392
    {
Packit 8dc392
        const T theta = T(2*i) / T(M_PI);
Packit 8dc392
        fromPoints.push_back (IMATH_INTERNAL_NAMESPACE::Vec3<T>(cos(theta), sin(theta), 0));
Packit 8dc392
        toPoints.push_back (IMATH_INTERNAL_NAMESPACE::Vec3<T>(cos(theta + M_PI/3.0), sin(theta + M_PI/3.0), 0));
Packit 8dc392
    }
Packit 8dc392
    verifyProcrustes (fromPoints, toPoints);
Packit 8dc392
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::Rand48 random (1209);
Packit 8dc392
    for (size_t numPoints = 1; numPoints < 10; ++numPoints)
Packit 8dc392
    {
Packit 8dc392
        fromPoints.clear(); toPoints.clear();
Packit 8dc392
        for (size_t i = 0; i < numPoints; ++i)
Packit 8dc392
        {
Packit 8dc392
            fromPoints.push_back (IMATH_INTERNAL_NAMESPACE::Vec3<T>(random.nextf(), random.nextf(), random.nextf()));
Packit 8dc392
            toPoints.push_back (IMATH_INTERNAL_NAMESPACE::Vec3<T>(random.nextf(), random.nextf(), random.nextf()));
Packit 8dc392
        }
Packit 8dc392
    }
Packit 8dc392
    verifyProcrustes (fromPoints, toPoints);
Packit 8dc392
Packit 8dc392
    // Test with some known matrices of varying degrees of quality:
Packit 8dc392
    testProcrustesWithMatrix<T> (m);
Packit 8dc392
Packit 8dc392
    m.translate (IMATH_INTERNAL_NAMESPACE::Vec3<T>(3, 4, 1));
Packit 8dc392
    testProcrustesWithMatrix<T> (m);
Packit 8dc392
Packit 8dc392
    m.translate (IMATH_INTERNAL_NAMESPACE::Vec3<T>(-10, 2, 1));
Packit 8dc392
    testProcrustesWithMatrix<T> (m);
Packit 8dc392
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::Eulerd rot (M_PI/3.0, 3.0*M_PI/4.0, 0);
Packit 8dc392
    m = m * rot.toMatrix44();
Packit 8dc392
    testProcrustesWithMatrix<T> (m);
Packit 8dc392
Packit 8dc392
    m.scale (IMATH_INTERNAL_NAMESPACE::Vec3<T>(1.5, 6.4, 2.0));
Packit 8dc392
    testProcrustesWithMatrix<T> (m);
Packit 8dc392
Packit 8dc392
    IMATH_INTERNAL_NAMESPACE::Eulerd rot2 (1.0, M_PI, M_PI/3.0);
Packit 8dc392
    m = m * rot.toMatrix44();
Packit 8dc392
Packit 8dc392
    m.scale (IMATH_INTERNAL_NAMESPACE::Vec3<T>(-1, 1, 1));
Packit 8dc392
    testProcrustesWithMatrix<T> (m);
Packit 8dc392
Packit 8dc392
    m.scale (IMATH_INTERNAL_NAMESPACE::Vec3<T>(1, 0.001, 1));
Packit 8dc392
    testProcrustesWithMatrix<T> (m);
Packit 8dc392
Packit 8dc392
    m.scale (IMATH_INTERNAL_NAMESPACE::Vec3<T>(1, 1, 0));
Packit 8dc392
    testProcrustesWithMatrix<T> (m);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
void
Packit 8dc392
testProcrustes ()
Packit 8dc392
{
Packit 8dc392
    std::cout << "Testing Procrustes algorithms in single precision..." << std::endl;
Packit 8dc392
    testProcrustesImp<float>();
Packit 8dc392
Packit 8dc392
    std::cout << "Testing Procrustes algorithms in double precision..." << std::endl;
Packit 8dc392
    testProcrustesImp<double>();
Packit 8dc392
}
Packit 8dc392
Packit 8dc392