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

[模板] 计算几何

时间:2022-08-15 00:03:13浏览次数:65  
标签: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,模板
From: https://www.cnblogs.com/zrzsblog/p/16586756.html

相关文章

  • Java一次计算简易计算器
    小白简易计算器第一次尝试写代码publicclassCalculator{publicstaticvoidmain(String[]args){//创建扫描对象Scannerscanner=newS......
  • 03-Spark的计算流程设计
    MR的计算流程设计step1:读取数据:Input功能一:实现分片,将读取到的数据进行划分,将不同的数据才能分给不同Task功能二:转换KVstep2:处理数据:Map、Shuffle、ReduceMap:负......
  • [2001年NOIP普及组] 数的计算
    算法分析:一个数可分为自身(+1)和自身除以2的数所带的次数,适合用递推从前往后推,比如说4可以分为2和1和自身所带表的数相加121231341424124注意:自身也要加1,若不足3直......
  • [NOIP2001 普及组] 数的计算
    试题分析:以4为例子:4后面可以跟上1,2组成14,24。14后面跟不了,24可以跟上1组成124,再加上4本身就可以得到4的种类:14,24,124,4。而我们只要算出1,2的种类就可以加起来得到4......
  • 编写一个简易计算器
    编写一个简易计算器思路用四个方法分别来实现加减乘除使用Scanner进行用户交互利用switch判断运算符 packagecom.ylmxy.method; ​ importjava.util.Sca......
  • AC自动机(Trie图)模板
    constintN=1e6+5;//tr就是多个模式串构造的fail树//cnt标记该位置上有无单词//id[i]:第i个模式串结尾所在的下标inttr[N][26],idx=1,nex[N],q[N],cnt[N],id......
  • DAC双通道模板
    #defineDAC_C#include"dac.h"floatDAC_DispenseA;floatDAC_DispenseB;voidMyDAC_Init(void){ GPIO_InitTypeDefGPIO_InitStructure; DAC_InitTypeDefDAC_InitStr......
  • 【模板】笛卡尔树
    笛卡尔树是一种二叉树,每个节点\(i\)由\(\left(k_i,w_i\right)\)构成,其中,\(k\)满足BST的性质,\(w\)满足堆的性质。若\(k,w\)互不相同,则构成的笛卡尔树唯一;两......
  • 可使用索尼的 PlayMemories Home 在个人计算机上管理并编辑照片和视频
    http://support.d-imaging.sony.co.jp/www/disoft/int/download/playmemories-home/win/zh-Hans/......
  • 1063 计算谱半径——20分
    在数学中,矩阵的“谱半径”是指其特征值的模集合的上确界。换言之,对于给定的n个复数空间的特征值{a1+b1i,...,an+bni},它们的模为实部与虚部的平方和的开方,而“谱半径”就......