/// Determines the Hermann-Mauguin symbol of the rotation-, rotoinversion- or
/// screw-axis.
std::string SymmetryElementRotationGenerator::determineSymbol(
    const SymmetryOperation &operation) const {
  const Kernel::IntMatrix &matrix = operation.matrix();

  int trace = matrix.Trace();
  int determinant = matrix.determinant();

  if (trace == 0 && determinant == -1) {
    return "-3";
  }

  std::string symbol;

  if (determinant < 0) {
    symbol += "-";
  }

  symbol += boost::lexical_cast<std::string>(operation.order());

  int translation =
      static_cast<int>(static_cast<double>(operation.order()) *
                       Kernel::V3D(determineTranslation(operation)).norm());

  if (translation != 0) {
    symbol += boost::lexical_cast<std::string>(translation);
  }

  return symbol;
}
/**
 * Transforms the operation using the internally stored SymmetryOperation.
 *
 * This method returns the transformed symmetry operation, using the
 * following relation:
 *
 *  S' = O^-1 * S * O
 *
 * Where O is the internally stored operation.
 *
 * @param operation :: SymmetryOperation to transform.
 * @return Transformed symmetry operation.
 */
SymmetryOperation GroupTransformation::transformOperation(
    const SymmetryOperation &operation) const {
  MatrixVectorPair<double, V3R> op =
      m_inversePair *
      MatrixVectorPair<double, V3R>(convertMatrix<double>(operation.matrix()),
                                    operation.vector()) *
      m_matrixVectorPair;

  return SymmetryOperation(op.getMatrix(), op.getVector());
}
Ejemplo n.º 3
0
/// Returns a vector with all symmetry operations that are part of the cyclic
/// group defined by the generating operation.
std::vector<SymmetryOperation>
CyclicGroup::generateAllOperations(const SymmetryOperation &operation) const {
  std::vector<SymmetryOperation> symOps(1, operation);
  symOps.reserve(operation.order());
  for (size_t i = 1; i < operation.order(); ++i) {
    symOps.push_back(operation * symOps.back());
  }

  return symOps;
}
/// Checks the trace and determinat of the matrix to determine if the matrix
/// belongs to a rotation.
bool SymmetryElementRotationGenerator::canProcess(
    const SymmetryOperation &operation) const {
  const Kernel::IntMatrix &matrix = operation.matrix();
  int determinant = matrix.determinant();
  int trace = matrix.Trace();

  return (abs(trace) != 3) && !(trace == 1 && determinant == -1);
}
/// Generates an instance of SymmetryElementMirror with the corresponding
/// symbol, axis and translation vector.
SymmetryElement_sptr SymmetryElementMirrorGenerator::generateElement(
    const SymmetryOperation &operation) const {
  const Kernel::IntMatrix &matrix = operation.matrix();

  V3R axis = determineAxis(matrix);
  V3R translation = determineTranslation(operation);
  std::string symbol = determineSymbol(operation);

  return boost::make_shared<SymmetryElementMirror>(symbol, axis, translation);
}
/**
 * Creates a SymmetryElement from a SymmetryOperation
 *
 * As detailed in the class description, the method checks whether there is
 * already a prototype SymmetryElement for the provided SymmetryOperation. If
 * not, it tries to find an appropriate generator and uses that to create
 * the prototype. Then it returns a clone of the prototype.
 *
 * @param operation :: SymmetryOperation for which to generate the element.
 * @return SymmetryElement for the supplied operation.
 */
SymmetryElement_sptr SymmetryElementFactoryImpl::createSymElement(
    const SymmetryOperation &operation) {
  std::string operationIdentifier = operation.identifier();

  SymmetryElement_sptr element = createFromPrototype(operationIdentifier);

  if (element) {
    return element;
  }

  AbstractSymmetryElementGenerator_sptr generator = getGenerator(operation);

  if (!generator) {
    throw std::runtime_error("Could not process symmetry operation '" +
                             operationIdentifier + "'.");
  }

  insertPrototype(operationIdentifier, generator->generateElement(operation));

  return createFromPrototype(operationIdentifier);
}
/// Determines the rotation sense according to the description in ITA 11.2.
SymmetryElementRotation::RotationSense
SymmetryElementRotationGenerator::determineRotationSense(
    const SymmetryOperation &operation, const V3R &rotationAxis) const {
  Kernel::V3D pointOnAxis1 = rotationAxis;
  Kernel::V3D pointOnAxis2 = rotationAxis * 2;
  Kernel::V3D pointOffAxis = rotationAxis + Kernel::V3D(2.1, 5.05, -1.1);
  Kernel::V3D generatedPoint = operation * pointOffAxis;

  Kernel::DblMatrix matrix(3, 3, false);
  matrix.setColumn(0, pointOnAxis2 - pointOnAxis1);
  matrix.setColumn(1, pointOffAxis - pointOnAxis1);
  matrix.setColumn(2, generatedPoint - pointOnAxis1);

  double determinant = matrix.determinant() * operation.matrix().determinant();

  if (determinant < 0) {
    return SymmetryElementRotation::Negative;
  } else {
    return SymmetryElementRotation::Positive;
  }
}
/// Returns the reduced vector of the operation.
V3R SymmetryElementWithAxisGenerator::determineTranslation(
    const SymmetryOperation &operation) const {
  return operation.reducedVector();
}
/// Checks that the trace of the matrix is 1 and the determinant is -1.
bool SymmetryElementMirrorGenerator::canProcess(
    const SymmetryOperation &operation) const {
  const Kernel::IntMatrix &matrix = operation.matrix();

  return matrix.Trace() == 1 && matrix.determinant() == -1;
}