Pregunta

Actualmente estoy poniendo en práctica un simple trazador de rayos en C ++. Tengo una clase denominada base ortonormal, que genera tres vectores unitarios ortogonales a partir de uno o dos vectores especificados, por ejemplo:

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_);
}

Estoy probando todos mis métodos con el marco unittest ++. El problema es que hay más de una solución posible para una base ortonormal válida. Por ejemplo esta prueba:

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() );
}

A veces tiene éxito, a veces falla, porque los vectores V y W también podría tener un efecto negativo 1, y todavía representan una base ortonormal válida. ¿Hay una manera de especificar varios valores esperados? ¿O usted sabe otra manera de hacer eso?

Es importante, que me sale de los valores reales y esperados impresos a la salida estándar, con el fin de depurar los métodos por lo que esta solución no hará el trabajo:

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() );
}
¿Fue útil?

Solución

Sin duda, si todo lo que se está probando es si su base es ortonormal, entonces eso es lo que necesita para la prueba?

// 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));

Otros consejos

Una posibilidad es crear su propia función 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);
}

Me haría uso de una función de utilidad o una clase de lo que puede hacer algo como esto:

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

Teniendo en cuenta, que la interpretación de la igualdad es algo raro, pero se debe imprimir todos los valores que desea ver sin la necesidad de introducir una macro personalizada.
Si usted está preocupado por EQUAL en ese contexto, una macro personalizada como CHECK_CONTAINS() no debería ser demasiado difícil de hacer.

VectorList sería construido como un temporal y operator() usarse para insertar valores en la lista contenida de Vectors, similar a Boost.Assign .

Enfoque básico:

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();
    }
};
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top