计算几何模板(未完待续)

目前基本都是从蓝书上摘录的。

有一部分需要线性代数的知识,但是蓝书作者并没有解释,个人觉得用数学知识推出来更有助于记忆,死记硬背板子容易忘。以后有机会的话我在这里写点注解。

二维基础操作:

 1 struct Point
 2 {
 3     double x, y;
 4     Point(double x = 0, double y = 0):x(x), y(y){}
 5 };
 6
 7 typedef Point Vector;
 8
 9 int dcmp(double x)//比较
10 {
11     const double eps = 1e-10;
12     if (fabs(x) < eps)    return 0;
13     else    return x < 0 ? -1 : 1;
14 }
15 Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); }
16 Vector operator - (Vector A, Vector B) { return Vector(A.x - B.x, A.y - B.y); }
17 Vector operator * (Vector A, double p) { return Vector(A.x * p, A.y * p); }
18 Vector operator / (Vector A, double p) { return Vector(A.x / p, A.y / p); }
19 bool operator < (const Point& A, const Point& B) { return A.x < B.x || (A.x == B.x && A.y < B. y); }
20 bool operator == (const Point& A, const Point& B) { return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0; }
21
22 const double PI = acos(-1.0);
23 double torad(double deg) { return deg/180 * PI; }//角度转弧度
24
25 double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }//点积
26
27 double Length(Vector A) { return sqrt(Dot(A, A)); }//长度
28
29 double Angle(Vector A, Vector B) { return acos(Dot(A, B)/Length(A)/Length(B)); }//角度
30
31 Vector Rotate(Vector A, double rad) { return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad)); }//旋转
32
33 double Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; }//叉积
34
35 double Area2(Point A, Point B, Point C) { return Cross(B-A, C-A);}//二倍的三角形面积
36
37 Vector Normal(Vector A) { double L = Length(A); return Vector(-A.y/L, A.x/L); }//向量的单位法线,旋转的特殊情况
38
39 Vector Get_Line_Projection(Point P, Point A, Point B)//P在AB方向上的映射
40 {
41      Vector v = B - A;
42       return A + v*(Dot(v, P-A) / Dot(v, v));
43 }
44
45 Vector Get_Line_Intersect(Vector A, Vector v, Vector B, Vector w)//两直线交点
46 {
47     Vector u = A - B;
48     double t = Cross(w, u) / Cross(v, w);
49     return A + v*t;
50 }
51
52 double Distance_to_Line(Point P, Point A, Point B)//点P到直线AB的距离
53 {
54     Vector v1 = B - A, v2 = P - A;
55     return fabs(Cross(v1, v2)) / Length(v1);
56 }
57
58 double Distance_to_Segment(Point P, Point A, Point B)//点P到线段AB的距离
59 {
60     Vector v1 = B - A, v2 = P - A, v3 = P - B;
61     if (A == B || dcmp(Dot(v1, v2)) < 0)    return Length(v2);//PA
62     else if (dcmp(Dot(v1, v3)) > 0)    return Length(v3);//PB
63     else    return fabs(Cross(v1, v2) / Length(v1));//PQ
64 }
65
66 bool On_Segment(Point P, Point A, Point B) { return dcmp(Cross(A - P, B - P)) == 0 && dcmp(Dot(A - P, B - P)) < 0; }//点在线段上
67
68 bool Segment_Proper_Intersection(Point a1, Point a2, Point b1, Point b2)//线段a1a2与b1b2相交(不包含端点)
69 {
70     double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1);
71     double c3 = Cross(b2 - b1, a1 - b1), c2 = Cross(b2 - b1, a2 - b1);
72     return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0;
73 }
74
75 double Polygon_Area(Point *p, int n)//多边形面积,逆时针取点0~n-1
76 {
77     double area = 0;
78     for (int i = 1; i < n-1; i++)
79         area += Cross(p[i] - p[0], p[i+1] - p[0]);
80     return area/2;
81 }
82
83 //基于复数的几何运算,效率不是很高
84 #include <complex>
85 typedef complex<double> Point;
86 typedef Point Vector;
87
88 double Dot(Vector A, Vector B) { return real(conj(A) * B); }// A(x+yi)的共轭(x-yi)乘以B,取实部
89 double Cross(Vector A, Vector B) { return imag(conj(A) * B); }//取虚部
90 Vector Rotate(Vector A, double rad) { return A * exp(Point(0, rad)); }//使用了欧拉公式:e^(0 + rad*i) = cos(rad) + sin(rad)*i,求完确实是旋转

圆相关(他那个两圆公切线看着有点奇怪先不贴了):

 1 struct Circle
 2 {
 3     Point c;
 4     double r;
 5     // Circle(Point a = (0, 0), double x = 0):c(a), r(x){}
 6     Point point(double seta) { return Point(c.x + cos(seta)*r, c.y + sin(seta)*r); }//已知角度求圆上某点
 7 };
 8
 9 struct Line
10 {
11     Point p;
12     Vector v;
13     Line(Point p, Vector v):p(p), v(v) { }
14
15     Point point(double t) { return p + v*t; }//已知参数t求直线上一点
16     Line move(double d) { return Line(p + Normal(v)*d, v); }//平移
17 };
18
19 int get_Tangents(Point P, Circle C, vector<Vector> &v)//过定点做圆的切线
20 {
21     Vector u = C.c - P;
22     double d = Length(u);
23
24     if (dcmp(d - C.r) < 0)    return 0;//点在圆内部
25     else if (dcmp(d - C.r) == 0)//点在圆上
26     {
27         v.push_back(Rotate(u, PI/2));
28         return 1;
29     }
30     else//两条切线
31     {
32         double a = asin(C.r / d);
33         v.push_back(Rotate(u, a));
34         v.push_back(Rotate(u, -a));
35         return 2;
36     }
37 }
38
39 int get_Line_Circle_Intersection(Line L, Circle C, vector<Point> &ans)//方程求解直线与圆的交点
40 {
41     double t1, t2;
42     double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;
43     double e = a*a + c*c, f = 2*(a*b + c*d), g = b*b + d*d - C.r*C.r;
44     double delta = f*f - 4*e*g;//判别式
45
46     if (dcmp(delta) < 0)    return 0;//相离
47     else if (dcmp(delta) == 0)//相切
48     {
49         t1 = t2 = -f/2/e;
50         ans.push_back(L.point(t1));
51         return 1;
52     }
53     else//相交
54     {
55         t1 = (-f + sqrt(delta)) / 2 / e;
56         t2 = (-f - sqrt(delta)) / 2 / e;
57         ans.push_back(L.point(t1)), ans.push_back(L.point(t2));
58         return 2;
59     }
60 }
61
62 inline double angle(Vector A) { return atan2(A.y, A.x); }//某向量极角
63
64 int get_Circle_Circle_Intersection(Circle C1, Circle C2, vector<Point> &v)//圆与圆的交点
65 {
66     double d = Length(C1.c - C2.c);
67     if (dcmp(d) == 0)
68     {
69         if (dcmp(C1.r - C2.r) == 0)    return -1;//重合
70         return 0;//同心
71     }
72     if (dcmp(C1.r + C2.r - d) < 0)    return 0;//外离
73     if (dcmp(fabs(C1.r - C2.r) - d) > 0)    return 0;//内含
74
75     double a = angle(C2.c - C1.c);
76     double da = acos((C1.r*C1.r + d*d - C2.r*C2.r) / (2*C1.r*d));//余弦公式
77     Point p1 = C1.point(a - da), p2 = C1.point(a + da);
78
79     v.push_back(p1);
80     if (p1 == p2)    return 1;
81     v.push_back(p2);
82     return 2;
83 }

原文地址:https://www.cnblogs.com/AlphaWA/p/10201050.html

时间: 2024-10-13 21:24:54

计算几何模板(未完待续)的相关文章

模板区域[未完待续](会定期的更新哦(有时间就更了))

写这个博客目的就是为了记录下学过的模板方便我这焫鷄复习吧//dalao们绕道 近期学的: (1)来自机房学长jjh大神教的求1~n的所有最小素因数和加上本焫鷄的批注 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath>//求1~n的最小质因数 using namespace std; const int MAXN=1e6+

Dancing Links 小结 (因为之前丢了一次稿,未完待续)

Dancing Links (DLX)是Knuth为了解决精确覆盖问题而提出的算法,很多搜索问题可以转化位精确覆盖问题从而使用Dancing Links解决(效率会比DFS高很多,因为里面常常蕴涵着意想不到的剪枝) 信息学竞赛中的DLX的问题类似网络流,只需建图+贴版即可 参考文献: 1.DLX的原理:Knuth的论文: 原版:http://arxiv.org/abs/cs/0011047 翻译版:http://wenku.baidu.com/view/d8f13dc45fbfc77da269b

whatweb.rb 未完待续

#!/usr/bin/env ruby #表示ruby的执行环境 =begin # ruby中用=begin来表示注释的开始 .$$$ $. .$$$ $. $$$$ $$. .$$$ $$$ .$$$$$$. .$$$$$$$$$$. $$$$ $$. .$$$$$$$. .$$$$$$. $ $$ $$$ $ $$ $$$ $ $$$$$$. $$$$$ $$$$$$ $ $$ $$$ $ $$ $$ $ $$$$$$. $ `$ $$$ $ `$ $$$ $ `$ $$$ $$' $ `$

把握linux内核设计思想系列(未完待续......)

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途] 把握linux内核设计思想(一):系统调用 把握linux内核设计思想(二):硬中断及中断处理 把握linux内核设计思想(三):下半部机制之软中断 把握linux内核设计思想(四):下半部机制之tasklet 把握linux内核设计思想(五):下半部机制之工作队列及几种机制的选择 把握linux内核设计思想(六):内核时钟中断 把握linux内核设计思想(七):内核定时器和

[译]App Framework 2.1 (1)之 Quickstart (未完待续)

最近有移动App项目,选择了 Hybrid 的框架Cordova  和  App Framework 框架开发. 本来应该从配置循序渐进开始写的,但由于上班时间太忙,这段时间抽不出空来,只能根据心情和兴趣,想到哪写到哪,前面的部分以后慢慢补上. App Framework 前生是是叫 jqMobi 注意大家不要和 jQuery Mobile 混淆了,它们是两个不同的框架,一开始我还真混淆了0.01秒. 这里我先翻译一下Quickstart 部分,一是自己工作上用的上,二是也想顺便练练英文,最关键

数据结构与算法之--高级排序:shell排序和快速排序【未完待续】

高级排序比简单排序要快的多,简单排序的时间复杂度是O(N^2),希尔(shell)排序的是O(N*(logN)^2),而快速排序是O(N*logN). 说明:下面以int数组的从小到大排序为例. 希尔(shell)排序 希尔排序是基于插入排序的,首先回顾一下插入排序,假设插入是从左向右执行的,待插入元素的左边是有序的,且假如待插入元素比左边的都小,就需要挪动左边的所有元素,如下图所示: ==> 图1和图2:插入右边的temp柱需要outer标记位左边的五个柱子都向右挪动 如图3所示,相比插入排序

git个人使用总结 —— idea命令行、撤销commit (未完待续)

近期在使用git,最开始在idea界面操作,后来要求用命令行.刚开始还不是很习惯,感觉很麻烦,用了几天后感觉爽极了! 其实git的命令也不是很多,熟悉一段时间就差不多能顺利使用了.使用过程中遇到了各种各样的问题,有些小问题就在这里集中总结一下. 1.idea命令行.git安装后就自带终端git bash,使用起来很方便.但是用idea开发,开发后还要在相应文件夹下打开git bash很麻烦.其实idea也带有终端terminal,在最下方可以找到,在这里就可以执行命令.但是如果是默认方式安装的g

Unity3D快捷键 未完待续

Unity3D 点选Object+F Object在当前视角居中 CTRL+1/2 Scene/Game视图的切换 MonoDevelop CTRL+K  删除光标所在行的该行后面的代码 CTRL + ALT +C  注释/不注释该行 CTRL+ DOWN  像鼠标滚轮一样向下拖 CTRL + UP 像鼠标滚轮一样向上拖 CTRL + F  查找该脚本 CTRL + SHIFT + F 查找全部脚本 CTRL + H 替换代码 CTRL + SHIFT +W 关掉所有脚本 Unity3D快捷键

NOIP2016 那些我所追求的 [未完待续]

人生第一场正式OI [Day -1] 2016-11-17 期中考试无心插柳柳成荫,考了全市第2班里第1(还不是因为只复习了不到两天考试),马上请了一个周的假准备NOIP(数学生物还是回去上课的) 灰哥跟我一块,tlq考吃了没请假 正好下个周老班出去学习了不害怕 星期4所有人都请假了,漫无目的地复习了一天题,参考题解补了一场模拟赛 晚上灰哥因为住宿直接回家了,还让我给XXX送纸条 SD NOIP的群好多人直播,我们就直播了个国际象棋(竟然有人说八皇后,我只升变了两个兵称为皇后),然而竟然默认开启

[daily][optimize] 去吃面 (python类型转换函数引申的性能优化)(未完待续)

前天,20161012,到望京面试.第四个职位,终于进了二面.好么,结果人力安排完了面试时间竟然没有通知我,也没有收到短信邀请.如果没有短信邀请门口的保安大哥是不让我进去大厦的.然后,我在11号接到了面试官直接打来的电话,问我为啥还没到,我说没人通知我我不知道呀.结果我就直接被他邀请去以访客的身份参加面试了.不知道人力的姑娘是不是认识我,且和我有仇,终于可以报复了... 然后,我终于如约到了,面试官带着我去前台登记.前台的妹子更萌...认为我是面试官,面试官是才是来面试的.我气质真的那么合吗?