其他分享
首页 > 其他分享> > [模板] 计算几何

[模板] 计算几何

作者:互联网

#include <bits/stdc++.h>

#define debug(x) std::cerr << "[" << __LINE__ << "]: " << #x << " = " << x << "\n"

using i64 = long long;

#define UP 1
#define DOWN -1
#define COIN 0
typedef double db;
constexpr db eps = 1e-8;
namespace Geo {
    inline db min(db a, db b) { return a < b ? a : b; }
    inline db max(db a, db b) { return a > b ? a : b; }
    struct Point {
        db x, y;
        Point(db x = 0, db y = 0) : x(x), y(y) {}
        Point operator+(const Point &b) { return Point(x + b.x, y + b.y); }
        Point operator-(const Point &b) const { return Point(x - b.x, y - b.y); }
        Point operator/(db m) { assert(m != 0); return Point(x / m, y / m); }
        db operator*(const Point &b) { return (x * b.x) + (y * b.y); }
        db operator^(const Point &b) { return (x * b.y) - (y * b.x); }
        friend std::ostream& operator<<(std::ostream& os,const Point& p) {
            os << "(" << p.x << "," << p.y << ")"; return os; 
        }
    };
    typedef Point Vector;
    struct Line {
        Point a, b;
        Line(db x1, db y1, db x2, db y2) :a(x1, y1), b(x2, y2) {}
    };
    struct Polygon {
        std::vector<Point> poly;
        Polygon() {}
        void add_point(Point& p) { poly.emplace_back(p); }
        void add_point(db x, db y) { poly.emplace_back(x, y); }
        friend std::ostream& operator<<(std::ostream& os, const Polygon& obj) {
            for (int i = 0, sz = (int)obj.poly.size(); i < sz; i++) {
                os << obj.poly[i] << " ";
            }
            return os;
        }
        bool inside(const Point& p);
        db Circumstance();
        db Area();
    };
    inline db cross(Point& o, Point& a, Point& b) {
        return (a - o) ^ (b - o);
    }
    Point operator*(const Point& a, db m) { return Point(a.x * m, a.y * m); }
    Point operator*(db m, const Point& b) { return b * m; }
    
    inline db dist (Point& a, Point& b) { return std::sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));}
    inline int dcmp(db x) { return std::abs(x) < eps ? 0 : (x < 0 ? -1 : 1);}
    inline int side(Line& p, Point& q) {
        return dcmp(cross(p.a, q, p.b));
    }
    bool intersect(Line& l1, Line& l2) {
        if (max(l1.a.x, l1.b.x) < min(l2.a.x, l2.b.x)) return false;//排斥实验 
        if (max(l1.a.y, l1.b.y) < min(l2.a.y, l2.b.y)) return false;
        if (max(l2.a.x, l2.b.x) < min(l1.a.x, l1.b.x)) return false;
        if (max(l2.a.y, l2.b.y) < min(l1.a.y, l1.b.y)) return false;
        if (cross(l1.a, l2.a, l1.b) * cross(l1.a, l1.b, l2.b) < 0) return false;//跨立实验
        if (cross(l2.a, l1.a, l2.b) * cross(l2.a, l2.b, l1.b) < 0) return false;
        return true;
    }
    Point interpoint(Line& l1, Line& l2) {
        Vector v1 = Point(l1.b.x - l1.a.x, l1.b.y - l1.a.y);
        Vector v2 = Point(l2.b.x - l2.a.x, l2.b.y - l2.a.y);
        Vector u = l1.a - l2.a;
        db t = (v2 ^ u) / (v1 ^ v2);
        return Point(l1.a.x + v1.x * t, l1.a.y + v1.y * t);
    }
    bool onSegment(const Point& p1, const Point& p2,const Point& q) {
        return dcmp((p1 - q) ^ (p2 - q)) == 0 && dcmp((p1 - q) * (p2 - q)) <= 0;
    }
    bool onSegment(const Line& l,const Point& q) {
        return dcmp((l.a - q) ^ (l.b - q)) == 0 && dcmp((l.a - q) * (l.b - q)) <= 0;
    }
    bool Polygon::inside(const Point& p) {
        bool flag = false;
        for (int i = 0, sz = (int)poly.size(), j = sz - 1; i < sz; j = i++) {
            Point p1 = poly[i];
            Point p2 = poly[j];
            if (onSegment(p1, p2, p)) return true;
            if ((dcmp(p1.y - p.y) > 0) != (dcmp(p2.y - p.y) > 0) \
                && dcmp(p.x - (p.y - p1.y) * (p1.x - p2.x) / (p1.y - p2.y) - p1.x) < 0 )
            {
                flag = !flag;
            }
            return flag;
        }
    }
    db Polygon::Circumstance() {
        db ans = 0;
        for (int i = 0, sz = (int)poly.size(), j = sz - 1; i < sz; j = i++) {
            ans += dist(poly[i], poly[j]);
        }
        return ans;
    }
    db Polygon::Area(){
        db ans = 0;
        Point assist(0, 0);
        for (int i = 0, sz = (int)poly.size(), j = sz - 1; i < sz; j = i++) {
            ans += (poly[i] - assist) ^ (poly[j] - assist);
        }
        return std::abs(ans) * 0.5;
    }
};
using namespace Geo;
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout << std::fixed << std::setprecision(10);
    Polygon po;
    int n;
    std::cin >> n;
    for (int i = 0; i < n; i++) {
        double u, v;
        std::cin >> u >> v;
        po.add_point(u, v);

    }
    //std::cout << (po.inside(Point(0.9, 0.5)) ? "INSIDE" : "OUTSIDE") << "\n";
    //std::cout << po.Area();
    Line l1(0, 1, 2, 3), l2(2, 3, 4, 1);
    std::cout << intersect(l1, l2) << "\n";
    std::cout << interpoint(l1, l2) << "\n";
    return 0;
}

 

标签:std,return,Point,db,poly,计算,几何,operator,模板
来源: https://www.cnblogs.com/zrzsblog/p/16586756.html