Question

Je suis exécute actuellement un traceur de rayons simple c ++. J'ai une classe appelée Base de Hilbert, qui génère trois vecteurs unitaires orthogonaux d'un ou de deux vecteurs déterminés, par exemple:

void
OrthonormalBasis::init_from_u ( const Vector& u )
{
    Vector n(1,0,0);
    Vector m(0,1,0);
    u_ = unify(u);
    v_ = cross(u_,n);
    if ( v_.length() < ONB_EPSILON )
        v_ = cross(u_,m);
    w_ = cross(u_,v_);
}

Je teste toutes mes méthodes avec unittest ++. Le problème est qu'il ya plus d'une solution possible pour une base orthonormée valide. Par exemple ce test:

TEST ( orthonormalbasis__should_init_from_u )
{
    Vector u(1,0,0);
    OrthonormalBasis onb;

    onb.init_from_u(u);

    CHECK_EQUAL( Vector( 1, 0, 0 ), onb.u() );
    CHECK_EQUAL( Vector( 0, 0, 1 ), onb.v() );
    CHECK_EQUAL( Vector( 0, 1, 0 ), onb.w() );
}

parfois il réussit, parfois, il échoue, car les vecteurs v et w pourraient aussi avoir un 1 négatif, et représentent toujours une base orthonormée valide. Y at-il un moyen de spécifier plusieurs valeurs attendues? Ou connaissez-vous une autre façon de le faire?

Il est important que je reçois les valeurs réelles et attendues imprimées au stdout, afin de déboguer les méthodes donc cette solution ne sera pas faire le travail:

TEST ( orthonormalbasis__should_init_from_u )
{
    Vector u(1,0,0);
    OrthonormalBasis onb;

    onb.init_from_u(u);

    CHECK_EQUAL( Vector( 1, 0, 0 ), onb.u() );
    CHECK(
        Vector( 0, 0, 1 ) == onb.v() ||
        Vector( 0, 0,-1 ) == onb.v() );
    CHECK(
        Vector( 0, 1, 0 ) == onb.w() ||
        Vector( 0,-1, 0 ) == onb.w() );
}
Était-ce utile?

La solution

Certes, si tout ce que vous testez est si votre base est orthonormé, alors c'est ce que vous devez tester?

// check orthogonality

CHECK_EQUAL( 0, dot(onb.u(), onb.v));
CHECK_EQUAL( 0, dot(onb.u(), onb.w));
CHECK_EQUAL( 0, dot(onb.v(), onb.w));

// check normality

CHECK_EQUAL( 1, dot(onb.u(), onb.u));
CHECK_EQUAL( 1, dot(onb.v(), onb.v));
CHECK_EQUAL( 1, dot(onb.w(), onb.w));

Autres conseils

Il est possible de créer votre propre fonction CHECK_MULTI:

void CHECK_MULTI(TYPE actual, vector<TYPE> expected, const char* message)
{
  for (element in expected) {
    if (element == actual) {
      // there's a test here so the test count is correct
      CHECK(actual, element);
      return;   
    }
  }
  CHECK(actual, expected);
}

J'utilise une fonction d'utilité ou de la classe afin que vous puissiez faire quelque chose comme ceci:

CHECK_EQUAL(VectorList(0,0,1)(0,0,-1), onb.v());

Étant donné que l'interprétation de l'égalité est un peu bizarre, mais il devrait vous imprimer toutes les valeurs que vous voulez voir sans la nécessité d'introduire une macro personnalisée.
Si vous êtes inquiet au sujet EQUAL dans ce contexte, une macro personnalisée comme CHECK_CONTAINS() ne devrait pas être trop difficile à faire.

VectorList serait construit en tant que temporaire et operator() être utilisé pour insérer des valeurs dans la liste contenue de Vectors, semblable à Boost.Assign .

Approche de base:

class VectorList {
    std::vector<Vector> data_;
public:
    VectorList(double a, double b, double c) {
        data_.push_back(Vector(a,b,c));
    }
    VectorList& operator()(double a, double b, double c) {
        data_.push_back(Vector(a,b,c));
        return *this;
    }
    bool operator==(const Vector& rhs) const {
        return std::find(data_.begin(), data_.end(), rhs) != data_.end();
    }
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top