예제 #1
0
/**
 * Determine if M has positive rank.  The maximum-magnitude entry of M is
 * returned.  The row in which it is contained is also returned.
 *
 * Based on "Geometric Tools" by David Eberly.
 */
static bool eig3_rank(const Matrix3x3 &m, Float& maxEntry, Vector &maxRow) {
    // Locate the maximum-magnitude entry of the matrix.
    maxEntry = -1.0f;
    int maxRowIndex = -1;
    for (int row = 0; row < 3; ++row) {
        for (int col = row; col < 3; ++col) {
            Float absValue = std::abs(m(row, col));
            if (absValue > maxEntry) {
                maxEntry = absValue;
                maxRowIndex = row;
            }
        }
    }

    // Return the row containing the maximum, to be used for eigenvector
    // construction.
    maxRow = m.row(maxRowIndex);

    return maxEntry >= std::numeric_limits<Float>::epsilon();
}
예제 #2
0
vec3 operator*(const Matrix3x3 &A, const vec3 &x)
{
    return vec3(dot(A.row(0), x),
                dot(A.row(1), x),
                dot(A.row(2), x));
}
예제 #3
0
void dthetaR_dtheta(Matrix3x3 &out, const Matrix3x3 &R, const Matrix3x3 &dR_dthetax, const Matrix3x3 &dR_dthetay, const Matrix3x3 &dR_dthetaz)
{
  //doesn't show up in <cmath> until c++11
#ifndef INFINITY
  const double INFINITY = std::numeric_limits<double>::infinity();
#endif

  double theta_y = asin(-R(2,0));

  Vector3 delta_x(Vector3::Zero());
  Vector3 delta_y, delta_z;

  //theta_y = asin(-R20)
  //dtheta_y/dfoo =
  //  -1/sqrt(1-R20^2) * dR20/dfoo
  delta_y.x() = dR_dthetax(2,0);
  delta_y.y() = dR_dthetay(2,0);
  delta_y.z() = dR_dthetaz(2,0);
  if (fabs(fabs(R(2,0)) - 1.0) < S_EPSILON) {
    //delta_y *= -INFINITY;
    //preserve zeros and avoid 0*infinity=nan
    delta_y.x() = (fabs(delta_y.x()) < S_EPSILON ? 0 : (delta_y.x() < 0 ? INFINITY : -INFINITY));
    delta_y.y() = (fabs(delta_y.y()) < S_EPSILON ? 0 : (delta_y.y() < 0 ? INFINITY : -INFINITY));
    delta_y.z() = (fabs(delta_y.z()) < S_EPSILON ? 0 : (delta_y.z() < 0 ? INFINITY : -INFINITY));
  }
  else
    delta_y /= -sqrt(1.0-R(2,0)*R(2,0));

  if (fabs(theta_y - M_PI_2) < S_EPSILON ||
      fabs(theta_y + M_PI_2) < S_EPSILON) {
    //theta_z = atan(R12/R02)
    //dtheta_z/dfoo =
    //  1/(1+(R12/R02)^2) * (R02*dR12/dfoo - R12*dR02/dfoo) / R02^2
    delta_z.x() = R(0,2)*dR_dthetax(1,2) - R(1,2)*dR_dthetax(0,2);
    delta_z.y() = R(0,2)*dR_dthetay(1,2) - R(1,2)*dR_dthetay(0,2);
    delta_z.z() = R(0,2)*dR_dthetaz(1,2) - R(1,2)*dR_dthetaz(0,2);
    double divisorz = R(1,2)*R(1,2)+R(0,2)*R(0,2);
    if (fabs(divisorz) < S_EPSILON) {
      //delta_z *= (divisorz >= 0 ? INFINITY : -INFINITY);
      //preserve zeros and avoid 0*infinity=nan
      delta_z.x() = (fabs(delta_z.x()) < S_EPSILON ? 0 : (delta_z.x() > 0 ? INFINITY : -INFINITY));
      delta_z.y() = (fabs(delta_z.y()) < S_EPSILON ? 0 : (delta_z.y() > 0 ? INFINITY : -INFINITY));
      delta_z.z() = (fabs(delta_z.z()) < S_EPSILON ? 0 : (delta_z.z() > 0 ? INFINITY : -INFINITY));
    }
    else
      delta_z /= divisorz;
  }
  else {
    //theta_x = atan(R21/R22)
    //dtheta_x/dfoo = 
    //  1/(1+(R21/R22)^2) * (R22*dR21/dfoo - R21*dR22/dfoo) / R22^2
    delta_x.x() = R(2,2)*dR_dthetax(2,1) - R(2,1)*dR_dthetax(2,2);
    delta_x.y() = R(2,2)*dR_dthetay(2,1) - R(2,1)*dR_dthetay(2,2);
    delta_x.z() = R(2,2)*dR_dthetaz(2,1) - R(2,1)*dR_dthetaz(2,2);
    double divisorx = R(2,2)*R(2,2)+R(2,1)*R(2,1);
    if (fabs(divisorx) < S_EPSILON) {
      //delta_x *= (divisorx >= 0 ? INFINITY : -INFINITY);
      //preserve zeros and avoid 0*infinity=nan
      delta_x.x() = (fabs(delta_x.x()) < S_EPSILON ? 0 : (delta_x.x() > 0 ? INFINITY : -INFINITY));
      delta_x.y() = (fabs(delta_x.y()) < S_EPSILON ? 0 : (delta_x.y() > 0 ? INFINITY : -INFINITY));
      delta_x.z() = (fabs(delta_x.z()) < S_EPSILON ? 0 : (delta_x.z() > 0 ? INFINITY : -INFINITY));
    }
    else
      delta_x /= divisorx;

    //theta_z = atan(R10/R00)
    //dtheta_z/dfoo =
    //  1/(1+(R10/R00)^2) * (R00*dR10/dfoo - R10*dR00/dfoo) / R00^2
    delta_z.x() = R(0,0)*dR_dthetax(1,0) - R(1,0)*dR_dthetax(0,0);
    delta_z.y() = R(0,0)*dR_dthetay(1,0) - R(1,0)*dR_dthetay(0,0);
    delta_z.z() = R(0,0)*dR_dthetaz(1,0) - R(1,0)*dR_dthetaz(0,0);
    double divisorz = R(0,0)*R(0,0)+R(1,0)*R(1,0);
    if (fabs(divisorz) < S_EPSILON) {
      //delta_z *= (divisorz >= 0 ? INFINITY : -INFINITY);
      //preserve zeros and avoid 0*infinity=nan
      delta_z.x() = (fabs(delta_z.x()) < S_EPSILON ? 0 : (delta_z.x() > 0 ? INFINITY : -INFINITY));
      delta_z.y() = (fabs(delta_z.y()) < S_EPSILON ? 0 : (delta_z.y() > 0 ? INFINITY : -INFINITY));
      delta_z.z() = (fabs(delta_z.z()) < S_EPSILON ? 0 : (delta_z.z() > 0 ? INFINITY : -INFINITY));
    }
    else
      delta_z /= divisorz;
  }

  out.row(0) = delta_x;
  out.row(1) = delta_y;
  out.row(2) = delta_z;
}