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(); }
/** * \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); }
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(); }
/** * \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(); } } }
/** * \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(); } }
/** * @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); }
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(); }
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; }