【模板】二维计算几何初步

template <class T>
struct point {
  T x, y;
  point() : point(0, 0) {}
  point(T x, T y) : x(x), y(y) {}
  friend point operator+(const point &lhs, const point &rhs) {
    return {lhs.x + rhs.x, lhs.y + rhs.y};
  }
  friend point operator-(const point &lhs, const point &rhs) {
    return {lhs.x - rhs.x, lhs.y - rhs.y};
  }
  friend point operator*(const point &lhs, const T &k) {  //数乘
    return {lhs.x * k, lhs.y * k};
  }
  friend T cross(const point &lhs, const point &rhs) {  //叉积
    return lhs.x * rhs.y - rhs.x * lhs.y;
  }
  friend T operator*(const point &lhs, const point &rhs) {  //向量内积
    return lhs.x * rhs.x + lhs.y * rhs.y;
  }
  friend T dist(const point &self) { return self * self; }  //模长
  friend bool quad(
      const point &self) {  //极角排序用于区分方向的象限(只判两个)
    return self.x <= 0 && self.y < 0 || self.x < 0 && self.y >= 0;
  }
  friend bool checkCross(const point &a, const point &b, const point &c,
                         const point &d) {  //两线段是否有交
    if (max(a.x, b.x) <= min(c.x, d.x) || max(c.x, d.x) <= min(a.x, b.x))
      return 0;
    if (max(a.y, b.y) <= min(c.y, d.y) || max(c.y, d.y) <= min(a.y, b.y))
      return 0;
    static const auto sgn = [&](const T &x) {
      return x == 0 ? 0 : (x < 0 ? -1 : 1);
    };
    return sgn(cross(a - c, d - c)) * sgn(cross(b - c, d - c)) < 0 &&
           sgn(cross(c - a, b - a)) * sgn(cross(d - a, b - a)) < 0;
  }
  friend bool operator==(const point &lhs, const point &rhs) {
    return lhs.x == rhs.x && lhs.y == rhs.y;
  }
  friend bool cmp(const point &a, const point &b) {
    return cross(a, b) ? cross(a, b) > 0 : dist(a) < dist(b);
  }
  friend bool operator<(const point &a, const point &b) {
    return a.x != b.x ? a.x < b.x : a.y < b.y;
  }
};
typedef point<LL> dot;
vector<dot> convexHull(vector<dot> a) {  //凸包
  static dot stk[1 << 18];
  dot cen = *min_element(a.begin(), a.end());
  sort(a.begin(), a.end(),
       [&](const dot &a, const dot &b) { return cmp(a - cen, b - cen); });
  int top = 0;
  for (dot v : a) {
    while (top >= 2 && cross(stk[top - 1] - stk[top], v - stk[top]) > 0) top--;
    stk[++top] = v;
  }
  return vector<dot>(stk + 1, stk + top + 1);
}
auto makeConvex(vector<dot> vec) { // 另一个版本,将三点共线删掉!
    // assert(is_sorted(vec.begin(), vec.end()));
    vector<dot> ret;
    for (dot p : vec) {
        while (ret.size() >= 2 && cross(ret.end()[-2] - ret.back(), p - ret.back()) <= 0) ret.pop_back();
        ret.push_back(p);
    }
    return ret;
}
vector<dot> minkowski(const vector<dot> &a,
                      const vector<dot> &b) {  //闵可夫斯基和
  vector<dot> c = {a[0] + b[0]};
  static dot sa[1 << 18], sb[1 << 18];
  int n = a.size(), m = b.size();
  for (int i = 0; i < n; i++) sa[i] = a[(i + 1) % n] - a[i];
  for (int i = 0; i < m; i++) sb[i] = b[(i + 1) % m] - b[i];
  int i = 0, j = 0;
  for (int k = 1; k < n + m; k++) {
    if (i < n && (j >= m || cmp(sa[i], sb[j])))
      c.push_back(c.back() + sa[i++]);
    else
      c.push_back(c.back() + sb[j++]);
  }
  return c;
}
auto minkowski(vector<dot> a, vector<dot> b) { // 另一个版本,注意必须叉掉三点共线
    if (a.empty())
        return b;
    if (b.empty())
        return a;
    for (int i = (int)a.size() - 1; i >= 1; i--) a[i] = a[i] - a[i - 1];
    for (int i = (int)b.size() - 1; i >= 1; i--) b[i] = b[i] - b[i - 1];
    vector<dot> c = { a[0] + b[0] };
    merge(a.begin() + 1, a.end(), b.begin() + 1, b.end(), back_inserter(c),
          [](dot p, dot q) { return cross(p, q) < 0; });
    for (int i = 1; i < (int)c.size(); i++) c[i] = c[i - 1] + c[i];
    return c;
}
bool checkIn(const vector<dot> &a, const dot &v) {  //点是否在凸包内
  dot cen = a[0];
  if (cmp(a.back() - cen, v - cen)) return 0;
  // if (cmp(v - cen, a[1] - cen)) return 0;
  if (cross(v - cen, a[1] - cen) ? cross(v - cen, a[1] - cen) > 0
                                 : dist(v - cen) > dist(a[1] - cen))
    return 0;
  auto p = lower_bound(
      a.begin() + 1, a.end(), v,
      [&](const dot &a, const dot &b) { return cmp(a - cen, b - cen); });
  return cross(*prev(p) - *p, v - *p) <= 0;
}

posted @ 2023-10-19 19:13  caijianhong  阅读(9)  评论(0编辑  收藏  举报