ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[模板] 计算几何

2022-08-15 00:00:44  阅读:159  来源: 互联网

标签:std return Point db poly 计算 几何 operator 模板


#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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有