示例#1
0
void Trajectory::shiftIntoBox(Positions &p) {
  if (p.getBox().empty()) return;
  const vector<Vector3D> &box = p.getBox();

  if (offsets.size() < p.size()) offsets.resize(p.size());

  // NOTE: This method was stolen from:
  //    gromacs-4.5.4/src/gmxlib/rmpbc.c:rm_gropbc()
  //  With the difference that we are accumulating offsets over the whole
  //  trajectory.

  for (unsigned n = 1; n < p.size(); n++) {
    Vector3D orig = p[n];
    p[n] += offsets[n];

    for (int m = 2; 0 <= m; m--) {
      double dist;

      while (0.75 * box[m][m] < fabs(dist = p[n][m] - p[n - 1][m])) {
        if (10 * box[m][m] < fabs(dist)) break; // Ignore unreasonable
        if (0 < dist) for (int d = 0; d <= m; d++) p[n][d] -= box[m][d];
        else for (int d = 0; d <= m; d++) p[n][d] += box[m][d];
      }
    }

    offsets[n] = p[n] - orig;

    LOG_DEBUG(5, "SHIFT: " << n << ' ' << p[n] << ' ' << offsets[n]);
  }
}
示例#2
0
static double alignment(const Positions &p1, const Positions &p2) {
  // Computes a metric of how aligned the two sets of positions are
  double d = 0;

  // Only consider every 8th position for better performance
  for (unsigned i = 1; i < p1.size(); i += 8)
    d += p1[i].distanceSquared(p2[i]);

  return sqrt(d) * 8 / p1.size();
}
示例#3
0
void DoubleTapDetector::initGesture(const Positions& positions)
{
    if (!_canBeDoubleTap)
    {
        // adding initial points
        if (positions.size() > _touchStartPos.size())
        {
            if (_touchStartPos.empty())
                _startGesture(positions);
            else
                _touchStartPos = positions;
            return;
        }

        // all points released, decide if potential double tap or abort
        if (positions.empty())
        {
            _canBeDoubleTap = _doubleTapTimer.isActive();
            if (!_canBeDoubleTap)
                cancelGesture();
        }
        return;
    }

    // points pressed again, check for double tap
    if (positions.size() == _touchStartPos.size() &&
        !MathUtils::hasMoved(positions, _touchStartPos, _doubleTapThresholdPx))
    {
        emit doubleTap(MathUtils::computeCenter(_touchStartPos),
                       _touchStartPos.size());
        _doubleTapTimer.stop();
    }

    // all points released, reset everything for next detection
    if (positions.empty())
        cancelGesture();
}
示例#4
0
void Trajectory::alignToLast(Positions &p) {
  // This function uses a random search, similar to simulated annealing, to
  // find a rotation of the current positions which is close to the previous.
  // This helps stabilize the view of the protein and improve interpolation
  // between frames.

  if (empty() || p.empty()) return;

  const Positions &last = *back();

  double align = alignment(p, last);
  double start = align;
  double angle = 2 * M_PI;
  unsigned rounds = 64;
  const double magicStoppingPoint = 0.3;
  double rate = pow(4.0 / 360.0, 1.0 / rounds); // Within 4 degrees

  for (unsigned j = 0; magicStoppingPoint < align && j < rounds; j++) {
    for (unsigned l = 0; l < 2; l++) {
      uint8_t r = Random::instance().rand<uint8_t>();
      Vector3D v(!(r & 1), !(r & 2), !(r & 4));
      AxisAngleD a(angle * l ? -1 : 1, v.normalize());

      // Rotate
      Positions tmp(p);
      for (unsigned i = 0; i < p.size(); i++)
        tmp[i] = a.rotate(tmp[i]);

      // Recheck
      double newAlign = alignment(tmp, last);
      if (newAlign < align) {
        // Accept
        align = newAlign;
        p = tmp;
      }
    }

    angle *= rate;
  }

  if (magicStoppingPoint <= start)
    LOG_DEBUG(3, "Alignment start=" << start << " end=" << align << " improved "
              << String::printf("%0.2f%%", (1.0 - align / start) * 100));
}