#include <bits/stdc++.h>
using namespace std;
using Real = long double;
Real g_err = 1e-9;
bool r_eq(Real x, Real y, Real err = g_err) {
  return abs(x - y) <= err || abs(x - y) <= abs(x) * err;
}
bool r_le(Real x, Real y, Real err = g_err) {
  return x - y <= err || x - y <= abs(x) * err;
}
bool r_ge(Real x, Real y, Real err = g_err) { return r_le(y, x, err); }
bool r_gt(Real x, Real y, Real err = g_err) { return !r_le(x, y, err); }
bool r_lt(Real x, Real y, Real err = g_err) { return !r_le(y, x, err); }
bool r_ne(Real x, Real y, Real err = g_err) { return !r_eq(x, y, err); }
bool rp_eq(Real x, Real y, Real err = g_err) { return abs(x - y) <= err; }
bool rp_le(Real x, Real y, Real err = g_err) { return x - y <= err; }
bool rp_ge(Real x, Real y, Real err = g_err) { return rp_le(y, x, err); }
bool rp_gt(Real x, Real y, Real err = g_err) { return !rp_le(x, y, err); }
bool rp_lt(Real x, Real y, Real err = g_err) { return !rp_le(y, x, err); }
bool rp_ne(Real x, Real y, Real err = g_err) { return !rp_eq(x, y, err); }
template <typename T>
bool updMax(T& tmax, const T& x) {
  if (x > tmax) {
    tmax = x;
    return true;
  } else {
    return false;
  }
}
template <typename T>
bool updMin(T& tmin, const T& x) {
  if (x < tmin) {
    tmin = x;
    return true;
  } else {
    return false;
  }
}
struct Point {
  Real x;
  Real y;
  Point() : x(0), y(0) {}
  Point(Real x_, Real y_) : x(x_), y(y_) {}
  bool operator==(const Point& p) const { return x == p.x && y == p.y; }
  bool operator!=(const Point& p) const { return !(*this == p); }
  bool sim(const Point& p, Real err = g_err) const {
    return r_eq(x, p.x, err) && r_eq(y, p.y, err);
  }
  static bool sim(const Point& p1, const Point& p2, Real err = g_err) {
    return p1.sim(p2, err);
  }
  Point& operator+=(const Point& p) {
    x += p.x;
    y += p.y;
    return *this;
  }
  Point& operator-=(const Point& p) {
    x -= p.x;
    y -= p.y;
    return *this;
  }
  Point& operator*=(Real k) {
    x *= k;
    y *= k;
    return *this;
  }
  Point& operator/=(Real k) {
    x /= k;
    y /= k;
    return *this;
  }
  Point operator+(const Point& p) const { return Point(*this) += p; }
  Point operator-(const Point& p) const { return Point(*this) -= p; }
  Point operator*(Real k) const { return Point(*this) *= k; }
  Point operator/(Real k) const { return Point(*this) /= k; }
  Point operator-() const { return (*this) * (-1); }
  Real len() const { return hypot(x, y); }
  static Point polar(Real r, Real th) {
    return Point(r * cos(th), r * sin(th));
  }
  Point rotate(Real th) const { return polar(len(), atan2(y, x) + th); }
  Point rotateQ() const { return Point(-y, x); }
  bool parallel(const Point& p, Real err = g_err) const {
    return r_eq(x * p.y, y * p.x, err);
  }
  Real innerProd(const Point& p) const { return x * p.x + y * p.y; }
  Real outerProd(const Point& p) const { return x * p.y - y * p.x; }
  Real arg() const { return atan2(y, x); }
  Real angle(const Point& p) const {
    Real th = atan2(p.y, p.x) - atan2(y, x);
    return th > 3.141592653589793238462643383279502884L
               ? th - 2 * 3.141592653589793238462643383279502884L
           : th <= -3.141592653589793238462643383279502884L
               ? th + 2 * 3.141592653589793238462643383279502884L
               : th;
  }
};
Point operator*(Real k, const Point& p) { return p * k; }
ostream& operator<<(ostream& os, const Point& p) {
  return os << "(" << p.x << ", " << p.y << ")";
}
struct Line;
ostream& operator<<(ostream& os, const Line& l);
struct Line {
  Point dir;
  Point base;
  static Line x_axis;
  static Line y_axis;
  static constexpr int SIDE_ON = 1;
  static constexpr int SIDE_P = 2;
  static constexpr int SIDE_N = 4;
  static constexpr int IST_NONE = -1;
  static constexpr int IST_ALL = -2;
  static constexpr int IST_ONE = 0;
  Line() : dir(0, 0), base(0, 0) {}
  Line(const Point& d, const Point& b) : dir(d), base(b) {}
  bool operator==(const Line& l) const {
    return dir == l.dir && base == l.base;
  }
  bool operator!=(const Line& l) const { return !(*this == l); }
  bool sim(const Line& l1, Real err = g_err) const {
    return dir.sim(l1.dir, err) && dir.sim(l1.base - base, err);
  }
  static bool sim(const Line& l1, const Line& l2, Real err = g_err) {
    return l1.sim(l2, err);
  }
  static Line connect(const Point& p1, const Point& p2) {
    return Line(p2 - p1, p1);
  }
  bool parallel(const Line& l, Real err = g_err) const {
    return dir.parallel(l.dir, err);
  }
  int ptSide(const Point& p, Real err = g_err) const {
    Real t1 = dir.y * (p.x - base.x);
    Real t2 = dir.x * (p.y - base.y);
    if (r_eq(t1, t2, err)) return SIDE_ON;
    if (r_lt(t1, t2, err)) return SIDE_P;
    return SIDE_N;
  }
  bool ptOn(const Point& p, Real err = g_err) const {
    return ptSide(p, err) == SIDE_ON;
  }
  tuple<int, Real, Real> intersect_coeff(const Line& l) const {
    if (dir.parallel(l.dir)) {
      if (ptOn(l.base))
        return make_tuple(IST_ALL, 0, 0);
      else
        return make_tuple(IST_NONE, 0, 0);
    } else {
      Real d = dir.x * (-l.dir.y) - (-l.dir.x) * dir.y;
      Point z = l.base - base;
      Real t1 = ((-l.dir.y) * z.x + l.dir.x * z.y) / d;
      Real t2 = ((-dir.y) * z.x + dir.x * z.y) / d;
      return {IST_ONE, t1, t2};
    }
  }
  Point unsafe_intersect(const Line& l) const {
    auto [rc, t1, t2] = intersect_coeff(l);
    assert(rc == IST_ONE);
    return base + t1 * dir;
  }
  Point perpend_foot(const Point& p) const {
    Real t1 = perpend_foot_coeff(p);
    return base + t1 * dir;
  }
  Real perpend_foot_coeff(const Point& p) const {
    auto [rc, t1, t2] = intersect_coeff(Line(dir.rotateQ(), p));
    return t1;
  }
  Real len(const Point& p) const { return (p - perpend_foot(p)).len(); }
};
ostream& operator<<(ostream& os, const Line& l) {
  return os << "[d " << l.dir << ", b " << l.base << ")";
}
Line Line::x_axis(Point(1, 0), Point(0, 0));
Line Line::y_axis(Point(0, 1), Point(0, 0));
struct Circle {
  Point c;
  Real r;
  Circle() : c(0, 0), r(0) {}
  Circle(const Point& c_, Real r_) : c(c_), r(r_) {}
  bool operator==(const Circle& o) const { return c == o.c && r == o.r; }
  bool operator!=(const Circle& o) const { return !(*this == o); }
  bool sim(const Circle& o, Real err = g_err) const {
    return c.sim(o.c, err) && r_eq(r, o.r, err);
  }
  static bool sim(const Circle& c1, const Circle& c2, Real err = g_err) {
    return c1.sim(c2, err);
  }
  bool ptOn(const Point& p, Real err = g_err) const {
    return r_eq((p - c).len(), r, err);
  }
  tuple<bool, Point, Point> intersect(const Line& o) const {
    Point f = o.perpend_foot(c);
    Real d = (f - c).len();
    if (d > r) return make_tuple(false, Point(), Point());
    Real t = sqrt(r * r - d * d);
    Point e = o.dir / o.dir.len();
    return make_tuple(true, f + t * e, f - t * e);
  }
  tuple<bool, Point, Point> intersect(const Circle& o) const {
    Real d = (o.c - c).len();
    if (d + r < o.r || d + o.r < r || r + o.r < d) {
      return make_tuple(false, Point(), Point());
    }
    Point v = (o.c - c) / d;
    Real t = (r * r - o.r * o.r + d * d) / (2 * d);
    Line l(v.rotateQ(), c + t * v);
    return intersect(l);
  }
};
ostream& operator<<(ostream& os, const Circle& circ) {
  return os << "[c " << circ.c << ", " << circ.r << "]";
}
Point circumcenter(const Point& z1, const Point& z2, const Point& z3) {
  Line l12((z2 - z1).rotateQ(), (z1 + z2) / 2);
  Line l23((z3 - z2).rotateQ(), (z2 + z3) / 2);
  return l12.unsafe_intersect(l23);
}
vector<Point> convex_hull(const vector<Point>& pts) {
  vector<Point> spts(pts);
  int n = pts.size();
  if (n == 0) return vector<Point>();
  auto sub = [&]() -> vector<Point> {
    vector<Point> ret;
    for (int i = 0; i < n; i++) {
      Point pt = spts.at(i);
      if (i > 0 && spts.at(i - 1).sim(spts.at(i))) continue;
      while (true) {
        int rs = ret.size();
        if (rs - 2 < 0) break;
        Point q0 = ret.at(rs - 2);
        Point q1 = ret.at(rs - 1);
        if ((q0 - q1).outerProd(pt - q1) < 0) break;
        ret.pop_back();
      }
      ret.push_back(pt);
    }
    ret.pop_back();
    return ret;
  };
  sort(spts.begin(), spts.end(), [](const Point& a, const Point& b) -> bool {
    if (a.x != b.x) return a.x < b.x;
    return a.y < b.y;
  });
  auto vec1 = sub();
  reverse(spts.begin(), spts.end());
  auto vec2 = sub();
  vec1.insert(vec1.end(), vec2.begin(), vec2.end());
  if (vec1.empty()) return vector<Point>({pts.at(0)});
  return vec1;
}
tuple<Real, int, int> convex_diameter(const vector<Point>& pts) {
  int n = pts.size();
  if (n <= 1) {
    cerr << "diameter is called with <=1 points.\n";
    exit(1);
  }
  auto conn = [&](long long int i, long long int j) -> Point {
    return pts.at(j % n) - pts.at(i % n);
  };
  auto edge = [&](long long int i) -> Point { return conn(i, i + 1); };
  if (n == 2) return make_tuple(conn(0, 1).len(), 0, 1);
  int k = -1;
  int m = -1;
  for (int i = 0, cnt = 0; cnt < 2; i++) {
    if (edge(i).y <= 0 && edge(i + 1).y > 0) {
      m = i + 1;
      cnt++;
    }
    if (edge(i).y >= 0 && edge(i + 1).y < 0) {
      k = i + 1;
      cnt++;
    }
  }
  Real vmax = 0;
  int k0 = -1, m0 = -1;
  bool run_k = true;
  bool run_m = true;
  while (run_k || run_m) {
    if (!run_m ||
        (run_k && edge(k).arg() - (-3.141592653589793238462643383279502884L) <=
                      edge(m).arg())) {
      if (updMax(vmax, conn(k + 1, m).len())) {
        k0 = k + 1, m0 = m;
      }
      k++;
      if (edge(k).y > 0) run_k = false;
    } else {
      if (updMax(vmax, conn(k, m + 1).len())) {
        k0 = k, m0 = m + 1;
      }
      m++;
      if (edge(m).y < 0) run_m = false;
    }
  }
  return make_tuple(vmax, k0 % n, m0 % n);
}
int in_triangle(const Point& pt, const Point& tr0, const Point& tr1,
                const Point& tr2) {
  auto chk = [&](const Point& b, const Point& e, const Point& p) -> bool {
    Point be = e - b;
    Point bp = p - b;
    Real r = r_eq(be.x, 0.0) ? bp.y / be.y : bp.x / be.x;
    return 0.0 <= r && r <= 1.0;
  };
  Line l01 = Line::connect(tr0, tr1);
  Line l12 = Line::connect(tr1, tr2);
  Line l20 = Line::connect(tr2, tr0);
  int side = l01.ptSide(tr2);
  if (side == Line::SIDE_ON) {
    if (!l01.ptOn(pt)) return Line::SIDE_N;
    return chk(tr0, tr1, pt) || chk(tr1, tr2, pt) || chk(tr2, tr0, pt)
               ? Line::SIDE_ON
               : Line::SIDE_N;
  }
  int other = side ^ (Line::SIDE_P | Line::SIDE_N);
  if (l01.ptSide(pt) == other || l12.ptSide(pt) == other ||
      l20.ptSide(pt) == other)
    return Line::SIDE_N;
  if (l01.ptSide(pt) == Line::SIDE_ON || l12.ptSide(pt) == Line::SIDE_ON ||
      l20.ptSide(pt) == Line::SIDE_ON)
    return Line::SIDE_ON;
  return Line::SIDE_P;
}
template <typename T1, typename T2>
ostream& operator<<(ostream& os, const pair<T1, T2>& p) {
  os << "(" << p.first << ", " << p.second << ")";
  return os;
}
template <typename T1, typename T2, typename T3>
ostream& operator<<(ostream& os, const tuple<T1, T2, T3>& t) {
  os << "(" << get<0>(t) << ", " << get<1>(t) << ", " << get<2>(t) << ")";
  return os;
}
template <typename T1, typename T2, typename T3, typename T4>
ostream& operator<<(ostream& os, const tuple<T1, T2, T3, T4>& t) {
  os << "(" << get<0>(t) << ", " << get<1>(t) << ", " << get<2>(t) << ", "
     << get<3>(t) << ")";
  return os;
}
template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
  os << '[';
  for (auto it = v.begin(); it != v.end(); it++) {
    if (it != v.begin()) os << ", ";
    os << *it;
  }
  os << ']';
  return os;
}
template <typename T, typename C>
ostream& operator<<(ostream& os, const set<T, C>& v) {
  os << '{';
  for (auto it = v.begin(); it != v.end(); it++) {
    if (it != v.begin()) os << ", ";
    os << *it;
  }
  os << '}';
  return os;
}
template <typename T, typename C>
ostream& operator<<(ostream& os, const unordered_set<T, C>& v) {
  os << '{';
  for (auto it = v.begin(); it != v.end(); it++) {
    if (it != v.begin()) os << ", ";
    os << *it;
  }
  os << '}';
  return os;
}
template <typename T, typename C>
ostream& operator<<(ostream& os, const multiset<T, C>& v) {
  os << '{';
  for (auto it = v.begin(); it != v.end(); it++) {
    if (it != v.begin()) os << ", ";
    os << *it;
  }
  os << '}';
  return os;
}
template <typename T1, typename T2, typename C>
ostream& operator<<(ostream& os, const map<T1, T2, C>& mp) {
  os << '[';
  for (auto it = mp.begin(); it != mp.end(); it++) {
    if (it != mp.begin()) os << ", ";
    os << it->first << ": " << it->second;
  }
  os << ']';
  return os;
}
template <typename T1, typename T2, typename C>
ostream& operator<<(ostream& os, const unordered_map<T1, T2, C>& mp) {
  os << '[';
  for (auto it = mp.begin(); it != mp.end(); it++) {
    if (it != mp.begin()) os << ", ";
    os << it->first << ": " << it->second;
  }
  os << ']';
  return os;
}
template <typename T, typename T2>
ostream& operator<<(ostream& os, const queue<T, T2>& orig) {
  queue<T, T2> que(orig);
  bool first = true;
  os << '[';
  while (!que.empty()) {
    T x = que.front();
    que.pop();
    if (!first) os << ", ";
    os << x;
    first = false;
  }
  return os << ']';
}
template <typename T, typename T2>
ostream& operator<<(ostream& os, const deque<T, T2>& orig) {
  deque<T, T2> que(orig);
  bool first = true;
  os << '[';
  while (!que.empty()) {
    T x = que.front();
    que.pop_front();
    if (!first) os << ", ";
    os << x;
    first = false;
  }
  return os << ']';
}
template <typename T, typename T2, typename T3>
ostream& operator<<(ostream& os, const priority_queue<T, T2, T3>& orig) {
  priority_queue<T, T2, T3> pq(orig);
  bool first = true;
  os << '[';
  while (!pq.empty()) {
    T x = pq.top();
    pq.pop();
    if (!first) os << ", ";
    os << x;
    first = false;
  }
  return os << ']';
}
template <typename T>
ostream& operator<<(ostream& os, const stack<T>& st) {
  stack<T> tmp(st);
  os << '[';
  bool first = true;
  while (!tmp.empty()) {
    T& t = tmp.top();
    if (first)
      first = false;
    else
      os << ", ";
    os << t;
    tmp.pop();
  }
  os << ']';
  return os;
}
ostream& operator<<(ostream& os, int8_t x) {
  os << (int32_t)x;
  return os;
}
template <class... Args>
string dbgFormat(const char* fmt, Args... args) {
  size_t len = snprintf(nullptr, 0, fmt, args...);
  char buf[len + 1];
  snprintf(buf, len + 1, fmt, args...);
  return string(buf);
}
template <class Head>
void dbgLog(bool with_nl, Head&& head) {
  cerr << head;
  if (with_nl) cerr << endl;
}
template <class Head, class... Tail>
void dbgLog(bool with_nl, Head&& head, Tail&&... tail) {
  cerr << head << " ";
  dbgLog(with_nl, forward<Tail>(tail)...);
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << setprecision(20);
  long long int n, q;
  cin >> n >> q;
  vector<Point> P(n);
  for (long long int i = 0; i < n; i++) {
    long long int x, y;
    cin >> x >> y;
    P[i] = Point(x, y);
  }
  Point g(0, 0);
  Real tots = 0;
  for (long long int i = 1; i < n - 1; i++) {
    Point lg = (P[0] + P[i] + P[i + 1]) / 3.0;
    Point v0i = P[i] - P[0];
    Point v0j = P[i + 1] - P[0];
    Real s = abs(v0i.x * v0j.y - v0i.y * v0j.x);
    tots += s;
    g += s * lg;
  }
  g = g / tots;
  vector<Real> L(n), Th(n);
  for (long long int i = 0; i < n; i++) {
    L[i] = (P[i] - g).len();
    Th[i] = (P[0] - g).angle(P[i] - g);
  };
  ;
  ;
  Real th0 = (P[0] - g).arg();
  ;
  long long int pinA = 0, pinB = 1;
  for (long long int _q = 0; _q < q; _q++) {
    long long int tp;
    cin >> tp;
    if (tp == 1) {
      long long int f, t;
      cin >> f >> t;
      f--;
      t--;
      if (f == pinA) {
        pinA = pinB;
        pinB = t;
      } else {
        pinB = t;
      };
      Point e(L[pinA], 0);
      Point pa = g + e.rotate(th0 + Th[pinA]);
      g = pa + e.rotate(3 * 3.141592653589793238462643383279502884L / 2);
      ;
      th0 += 3.141592653589793238462643383279502884L / 2.0 - (th0 + Th[pinA]);
      ;
    } else if (tp == 2) {
      long long int v;
      cin >> v;
      v--;
      Point e(L[v], 0);
      Point pv = g + e.rotate(th0 + Th[v]);
      cout << pv.x << " " << pv.y << "\n";
    }
  }
  return 0;
}
