Exemple #1
0
Vec3D Reorient::fromNormal() {
  Crystal* c;
  if (!fromIndex.isNull() && (c = Clip::getInstance()->getMostRecentCrystal(true))) {
    if (ui->RezicheckBox->isChecked()) {
      return c->hkl2Reziprocal(fromIndex).normalized();
    } else {
      return c->uvw2Real(fromIndex).normalized();
    }
  }
  return Vec3D();
}
Exemple #2
0
/**
 * \brief This function is called when a crystal detects a collision with this entity.
 * \param crystal the crystal
 * \param collision_mode the collision mode that detected the event
 */
void Arrow::notify_collision_with_crystal(Crystal& crystal, CollisionMode collision_mode) {

  if (collision_mode == COLLISION_OVERLAPPING && is_flying()) {

    crystal.activate(*this);
    attach_to(crystal);
  }
}
/**
 * \copydoc MapEntity::is_crystal_obstacle
 */
bool CustomEntity::is_crystal_obstacle(Crystal& crystal) {

    const TraversableInfo& info = get_can_traverse_entity_info(crystal.get_type());
    if (!info.is_empty()) {
        return !info.is_traversable(*this, crystal);
    }
    return Detector::is_crystal_obstacle(crystal);
}
Exemple #4
0
Vec3D Reorient::toNormal() {
  int index=ui->toCombo->currentIndex();
  if (index>2) {
    Crystal* c;
    if (!toIndex.isNull() && (c = Clip::getInstance()->getMostRecentCrystal(true))) {
      if (index==3) {
        return c->hkl2Reziprocal(fromIndex).normalized();
      } else {
        return c->uvw2Real(fromIndex).normalized();
      }
    }
  } else {
    Vec3D normal;
    normal(index)=1;
    return normal;
  }
  return Vec3D();
}
Exemple #5
0
/**
 * \brief This function is called when a crystal detects a collision with this entity.
 * \param crystal the crystal
 * \param collision_mode the collision mode that detected the event
 */
void Boomerang::notify_collision_with_crystal(Crystal &crystal, CollisionMode collision_mode) {

  if (collision_mode == COLLISION_RECTANGLE) {

    crystal.activate(*this);
    if (!is_going_back()) {
      go_back();
    }
  }
}
Exemple #6
0
/**
 * \brief This function is called when a crystal detects a collision with this entity.
 * \param crystal the crystal
 * \param collision_mode the collision mode that detected the event
 */
void CarriedItem::notify_collision_with_crystal(Crystal& crystal, CollisionMode collision_mode) {

  if (collision_mode == COLLISION_OVERLAPPING
      && is_being_thrown()
      && !can_explode()) {

    crystal.activate(*this);
    break_item();
  }
}
Exemple #7
0
/**
 * @brief This function is called when a crystal detects a collision with this entity.
 * @param crystal the crystal
 * @param collision_mode the collision mode that detected the event
 */
void Hookshot::notify_collision_with_crystal(Crystal& crystal, CollisionMode collision_mode) {

  if (is_flying()) {

    crystal.activate(*this);
    if (!is_going_back()) {
      go_back();
    }
  }
}
/**
 * \brief This function is called when a the sprite of a crystal
 * detects a pixel-precise collision with a sprite of this entity.
 * \param crystal the crystal
 * \param sprite_overlapping the sprite of the current entity that collides with the crystal
 */
void Explosion::notify_collision_with_crystal(Crystal& crystal, Sprite& /* sprite_overlapping */) {

  crystal.activate(*this);
}
/**
 * \copydoc MapEntity::notify_collision_with_crystal(Crystal&,Sprite&)
 */
void CustomEntity::notify_collision_with_crystal(
    Crystal& crystal, Sprite& sprite_overlapping) {

    notify_collision_from(crystal, crystal.get_sprite(), sprite_overlapping);
}
Exemple #10
0
Crystal RandSpg::randSpgCrystal(const randSpgInput& input)
{
  START_FT;

  // Convenience: so we don't have to say 'input.<option>' for every call
  uint spg                                                      = input.spg;
  const vector<uint>& atoms                                     = input.atoms;
  const latticeStruct& latticeMins                              = input.latticeMins;
  const latticeStruct& latticeMaxes                             = input.latticeMaxes;
  double IADScalingFactor                                       = input.IADScalingFactor;
  double minRadius                                              = input.minRadius;
  const std::vector<std::pair<uint, double>>& manualAtomicRadii = input.manualAtomicRadii;
  double minVolume                                              = input.minVolume;
  double maxVolume                                              = input.maxVolume;
  vector<pair<uint, char>> forcedWyckAssignments                = input.forcedWyckAssignments;
  char verbosity                                                = input.verbosity;
  int numAttempts                                               = input.maxAttempts;
  bool forceMostGeneralWyckPos                                  = input.forceMostGeneralWyckPos;

  // Change the atomic radii as necessary
  ElemInfo::applyScalingFactor(IADScalingFactor);

  // Set the min radius
  ElemInfo::setMinRadius(minRadius);

  // Set some explicit radii
  for (size_t i = 0; i < manualAtomicRadii.size(); i++) {
    uint atomicNum = manualAtomicRadii[i].first;
    double rad = manualAtomicRadii[i].second;
    ElemInfo::setRadius(atomicNum, rad);
  }

  systemPossibilities possibilities = RandSpgCombinatorics::getSystemPossibilities(spg, atoms);

  if (possibilities.size() == 0) {
    cout << "Error in RandSpg::" << __FUNCTION__ << "(): this spg '" << spg
         << "' cannot be generated with this composition\n";
    return Crystal();
  }

  // force the most general Wyckoff position to be used at least once?
  if (forceMostGeneralWyckPos)
    possibilities = RandSpgCombinatorics::removePossibilitiesWithoutGeneralWyckPos(possibilities, spg);

  if (possibilities.size() == 0) {
    cout << "Error in RandSpg::" << __FUNCTION__ << "(): this spg '" << spg
         << "' cannot be generated with this composition.\n";
    cout << "It can be generated if option 'forceMostGeneralWyckPos' is "
         << "turned off, but the correct spacegroup will not be guaranteed.\n";
    return Crystal();
  }

  // The tuple is as follows: <atomicNum, wyckLet, numTimesUsed>
  vector<tuple<uint, char, uint>> forcedWyckAssignmentsAndNumber = getForcedWyckAssignmentsAndNumber(forcedWyckAssignments);

  for (size_t i = 0; i < forcedWyckAssignmentsAndNumber.size(); i++) {
    possibilities =
      RandSpgCombinatorics::removePossibilitiesWithoutWyckPos(possibilities,
                  get<1>(forcedWyckAssignmentsAndNumber[i]),
                  get<2>(forcedWyckAssignmentsAndNumber[i]),
                  get<0>(forcedWyckAssignmentsAndNumber[i]));
  }

  if (possibilities.size() == 0) {
    cout << "Error in RandSpg::" << __FUNCTION__ << "(): this spg '" << spg
         << "' cannot be generated with this composition due to the forced "
         << "Wyckoff position constraints.\nPlease change them or remove them "
         << "if you wish to generate the space group.\n";
    return Crystal();
  }

  //RandSpgCombinatorics::printSystemPossibilities(possibilities);
  // If we desire verbose output, print the system possibility to the log file
  if (verbosity == 'v')
    appendToLogFile(RandSpgCombinatorics::getVerbosePossibilitiesString(possibilities));

  // Create a modified forced wyck vector for later...
  vector<pair<uint, wyckPos>> modifiedForcedWyckVector = getModifiedForcedWyckVector(forcedWyckAssignments, spg);

  // Begin the attempt loop!
  for (size_t i = 0; i < numAttempts; i++) {

    Crystal crystal = createValidCrystal(spg, latticeMins, latticeMaxes,
                                         minVolume, maxVolume);

    // Now, let's assign some atoms!
    atomAssignments assignments = RandSpgCombinatorics::getRandomAtomAssignments(possibilities, modifiedForcedWyckVector);

    //printAtomAssignments(assignments);
    // If we desire any output, print the atom assignments to the log file
    if (verbosity == 'r' || verbosity == 'v')
      appendToLogFile(getAtomAssignmentsString(assignments));

    if (assignments.size() == 0) {
      cout << "Error in RandSpg::randSpgXtal(): atoms were not successfully"
           << " assigned positions in assignAtomsToWyckPos()\n";
      continue;
    }

#ifdef RANDSPG_DEBUG
    cout << "\natomAssignments are the following (atomicNum, wyckLet, wyckPos):"
         << "\n";
    for (size_t j = 0; j < assignments.size(); j++)
      cout << "  " << assignments[j].second << ", "
           << getWyckLet(assignments[j].first)
           << ", " << getWyckCoords(assignments[j].first) << "\n";
    cout << "\n";
#endif

    bool assignmentsSuccessful = true;
    for (size_t j = 0; j < assignments.size(); j++) {
      const wyckPos& pos = assignments[j].first;
      uint atomicNum = assignments[j].second;
      if (!addWyckoffAtomRandomly(crystal, pos, atomicNum, spg)) {
        assignmentsSuccessful = false;
        break;
      }
    }

    // If we succeeded, and the number of atoms match, return the crystal!
    // There are rare cases where an atom may be placed on top of another
    // one and the essentially get merged into one. We check to make sure the
    // sizes of the atomic numbers match for this reason. We shouldn't have to
    // worry about types.
    if (assignmentsSuccessful &&
        atoms.size() == crystal.getVectorOfAtomicNums().size()) {
      if (verbosity != 'n') appendToLogFile("*** Success! ***\n");
      return crystal;
    }
    else {
      if (verbosity == 'r' || verbosity == 'v') {
        stringstream ss;
        ss << "Failed to add atoms to satisfy MinIAD.\nObtaining new atom "
           << "assignments and trying again. Failure count: " << i + 1 << "\n\n";
        appendToLogFile(ss.str());
      }
      continue;
    }
  }

  // If we made it here, we failed to generate the crystal
  stringstream errMsg;
  errMsg << "After " << numAttempts << " attempts: failed to generate "
         << "a crystal of spg " << spg << ".\n";
  if (verbosity != 'n') appendToLogFile(errMsg.str());
  cerr << errMsg.str();
  return Crystal();
}
Exemple #11
0
bool RandSpg::addWyckoffAtomRandomly(Crystal& crystal, const wyckPos& position,
                                     uint atomicNum, uint spg, int maxAttempts)
{
  START_FT;
#ifdef RANDSPG_WYCK_DEBUG
  cout << "At beginning of addWyckoffAtomRandomly(), atom info is:\n";
  crystal.printAtomInfo();
  cout << "Attempting to add an atom of atomicNum " << atomicNum
       << " at position " << getWyckCoords(position) << "\n";
#endif

  // If this contains a unique position, we only need to try once
  // Otherwise, we'd be repeatedly trying the same thing...
  if (containsUniquePosition(position)) {
    maxAttempts = 1;
  }

  int i = 0;
  bool success = false;
  do {
    // Generate random coordinates in the wyckoff position
    // Numbers are between 0 and 1
    double x = getRandDouble(0,1);
    double y = getRandDouble(0,1);
    double z = getRandDouble(0,1);

    vector<string> components = split(getWyckCoords(position), ',');

    // Interpret the three components of the Wyckoff position coordinates...
    double newX = interpretComponent(components[0], x, y, z);
    double newY = interpretComponent(components[1], x, y, z);
    double newZ = interpretComponent(components[2], x, y, z);

    // interpretComponenet() returns -1 if it failed to read the component
    if (newX == -1 || newY == -1 || newZ == -1) {
      cout << "addWyckoffAtomRandomly() failed due to a component not being "
           << "read successfully!\n";
      return false;
    }

    atomStruct newAtom(atomicNum, newX, newY, newZ);
    crystal.addAtom(newAtom);

    // Check the interatomic distances
    if (crystal.areIADsOkay(newAtom)) {
      // Now try to fill the cell using this new atom
      if (crystal.fillCellWithAtom(spg, newAtom)) success = true;
    }
    if (!success) {
      // Remove this atom and try again
      crystal.removeAtom(newAtom);
    }

    i++;
  } while (i < maxAttempts && !success);

  if (!success) return false;

#ifdef RANDSPG_WYCK_DEBUG
    cout << "After an atom with atomic num " << atomicNum << " was added and "
         << "the cell filled, the following is the atom info:\n";
    crystal.printAtomInfo();
#endif

  return true;
}