计算几何基础(模板)

1.多边形面积计算

1     double S(Point p[],int n)
2     {
3         double ans = 0;
4         p[n] = p[0];
5         for(int i=1;i<n;i++)
6            ans += cross(p[0],p[i],p[i+1]);
7         if(ans < 0) ans = -ans;
8         return ans / 2.0;
9     }  

2.求凸包

 1     bool cmp(Point A,Point B)
 2     {
 3         double k = cross(MinA,A,B);
 4         if(k<0) return 0;
 5         if(k>0) return 1;
 6         return dist(MinA,A)<dist(MinA,B);
 7     }
 8
 9     void Graham(Point p[],int n)
10     {
11         for(int i=1;i<n;i++)
12            if(p[i].y<p[0].y || (p[i].y == p[0].y && p[i].x < p[0].x))
13                 swap(p[i],p[0]);
14         MinA = p[0];
15         p[n] = p[0];
16         sort(p+1,p+n,cmp);
17         stack[0] = p[0];
18         stack[1] = p[1];
19         top = 2;
20         for(int i=2;i<n;i++)
21         {
22             while(top >= 2 && cross(stack[top-2],stack[top-1],p[i])<=0) top--;
23             stack[top++] = p[i];
24         }
25     }  

3.任意多边形求重心

 1     Point Gravity(Point p[],int n)
 2     {
 3         Point O,t;
 4         O.x = O.y = 0;
 5         t.x = t.y = 0;
 6         p[n] = p[0];
 7         double A = 0;
 8         for(int i=0; i<n; i++)
 9             A += cross(O,p[i],p[i+1]);
10         A /= 2.0;
11         for(int i=0; i<n; i++)
12         {
13             t.x += (p[i].x + p[i+1].x) * cross(O,p[i],p[i+1]);
14             t.y += (p[i].y + p[i+1].y) * cross(O,p[i],p[i+1]);
15         }
16         t.x /= 6*A;
17         t.y /= 6*A;
18         return t;
19     }  

4.求线段交点的坐标

 1     bool Segment_crossing(Segment u,Segment v)   /** 判断线段是否相交 */
 2     {
 3              return((max(u.a.x,u.b.x)>=min(v.a.x,v.b.x))&&
 4                (max(v.a.x,v.b.x)>=min(u.a.x,u.b.x))&&
 5                (max(u.a.y,u.b.y)>=min(v.a.y,v.b.y))&&
 6                (max(v.a.y,v.b.y)>=min(u.a.y,u.b.y))&&
 7                (cross(v.a,u.b,u.a)*cross(u.b,v.b,u.a)>=0)&&
 8                (cross(u.a,v.b,v.a)*cross(v.b,u.b,v.a)>=0));
 9     }
10
11     /**求直线交点的坐标,如果没有交点返回NULL,否则返回交点p的地址*/
12     Point* CrossPoint(Segment u,Segment v)
13     {
14         Point p;
15         if(Segment_crossing(u,v))
16         {
17             p.x=(cross(v.b,u.b,u.a)*v.a.x-cross(v.a,u.b,u.a)*v.b.x)/(cross(v.b,u.b,u.a)-cross(v.a,u.b,u.a));
18             p.y=(cross(v.b,u.b,u.a)*v.a.y-cross(v.a,u.b,u.a)*v.b.y)/(cross(v.b,u.b,u.a)-cross(v.a,u.b,u.a));
19             return &p;
20         }
21         return NULL;
22     }  

5.三角形外接圆的半径与圆心

 1     Point Circle_Point(Point A,Point B,Point C)
 2     {
 3         double a=dist(B,C);
 4         double b=dist(A,C);
 5         double c=dist(A,B);
 6         double p=(a+b+c)/2.0;
 7         double S=sqrt(p*(p-a)*(p-b)*(p-c));
 8         R=(a*b*c)/(4*S);    //三角形外接圆的半径为R
 9
10         double t1=(A.x*A.x+A.y*A.y-B.x*B.x-B.y*B.y)/2;
11         double t2=(A.x*A.x+A.y*A.y-C.x*C.x-C.y*C.y)/2;
12         Point center;
13         center.x=(t1*(A.y-C.y)-t2*(A.y-B.y))/((A.x-B.x)*(A.y-C.y)-(A.x-C.x)*(A.y-B.y));
14         center.y=(t1*(A.x-C.x)-t2*(A.x-B.x))/((A.y-B.y)*(A.x-C.x)-(A.y-C.y)*(A.x-B.x));
15         return center;
16     }  

6.旋转卡壳求凸包的直径,也就是平面最远点对,p[]为凸包的点集

 1     double rotating_calipers(Point p[],int n)
 2     {
 3         int k = 1;
 4         double ans = 0;
 5         p[n] = p[0];
 6         for(int i=0;i<n;i++)
 7         {
 8             while(fabs(cross(p[i],p[i+1],p[k])) < fabs(cross(p[i],p[i+1],p[k+1])))
 9                  k = (k+1) % n;
10             ans = max(ans, max(dist(p[i],p[k]),dist(p[i+1],p[k])));
11         }
12         return ans;
13     }  

7.求凸包的宽度

 1     double rotating_calipers(Point p[],int n)
 2     {
 3         int k = 1;
 4         double ans = 0x7FFFFFFF;
 5         p[n] = p[0];
 6         for(int i=0;i<n;i++)
 7         {
 8             while(fabs(cross(p[i],p[i+1],p[k])) < fabs(cross(p[i],p[i+1],p[k+1])))
 9                  k = (k+1) % n;
10             double tmp = fabs(cross(p[i],p[i+1],p[k]));
11             double d   = dist(p[i],p[i+1]);
12             ans = min(ans,tmp/d);
13         }
14         return ans;
15     }  
时间: 2024-10-30 16:49:16

计算几何基础(模板)的相关文章

计算几何基础 模板

计算几何拖了这么久,终于拖到省选前了. 参考: https://oi.men.ci/geometry-notes/ https://www.cnblogs.com/fly-in-milkyway/p/10569895.html https://blog.csdn.net/clover_hxy/article/details/53966405 https://www.cnblogs.com/lstoi/p/9791654.html 基础部分 #include <cmath> #include &

知识点 - 计算几何基础

知识点 - 计算几何基础 讲义 点 我们把点 \(\mathbf r\) 看成从 \(\mathbf 0\) 到 \(\mathbf r\)的向量 \(\vec{\mathbf r}\) #define ftype long double struct point2d { ftype x, y; point2d() {} point2d(ftype x, ftype y): x(x), y(y) {} point2d& operator+=(const point2d &t) { x +=

nyis oj 68 三点顺序 (计算几何基础)

三点顺序 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描写叙述 如今给你不共线的三个点A,B,C的坐标,它们一定能组成一个三角形,如今让你推断A,B,C是顺时针给出的还是逆时针给出的? 如: 图1:顺时针给出 图2:逆时针给出 <图1>                   <图2> 输入 每行是一组測试数据,有6个整数x1,y1,x2,y2,x3,y3分别表示A,B,C三个点的横纵坐标.(坐标值都在0到10000之间) 输入0 0 0 0 0 0表示输入

计算几何基础——【点积和叉积的用处】

计算几何是算法竞赛的一大块,而叉积是计算机和的基础. 首先叉积是计算说向量之间的叉积,那么我们可以这样定义向量,以及向量的运算符重载. struct Point { double x,y; Point(double x=0,double y=0):x(x),y(y) {} }; typedef Point Vector; Vector operator + (Vector A,Vector B) { return Vector(A.x+B.x,A.y+B.y); } Vector operato

【kuangbin专题】计算几何基础(极角相关)

[POJ 1696] Space Ants [题目大意] 给定多个点,对他们按照下面的规则排序,每个都在前一个点组成的左边,并且连线不相交(典型如图) [题目分析] 不断进行极角排序,不断选取一定区域内最符合要求的解 [代码] 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #define ll double 5 using namespace std; 6 const double eps

BZOJ_1610_[Usaco2008_Feb]_Line连线游戏_(计算几何基础+暴力)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1610 给出n个点,问两两确定的直线中,斜率不同的共有多少条. 分析 暴力枚举直线,算出来斜率放在k数组里面(斜率不存在记为INF),然后去个重统计个数就行了. 其实特水... 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=200+5; 5 const double eps=1e-8,INF=0x7f

计算几何及其应用——计算几何基础

写在前面:当时开计算几何这个专题神奇的从解析几何开始了,然后最近发现<计算几何及应用(金博)>这本书前面那章忽略掉了一些重要的东西比如说点定位.半平面相交之类的东西,恰好还有一些和计算几何扯上边但是不需要算法的简单题目没有整理,故在此开辟一块小空间. 我们再来看一道有关几何的问题.(Problem source:hdu2073)    数理分析:虽然这道题异常的简单,基本算不上计算几何这个专题当中的题目,但是把它拿到这里来,是源于这道简单几何题的思路其实体现了计算几何整个体系中比较重要的思维.

UVA 10652 Board Wrapping(计算几何基础,求凸包)

题目链接:传送门 分析: 没有什么好说的就是求一个凸包就好了.可以当作模板. 代码如下: #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; const double eps = 1e-10; //判断符号,提高精度 int dcmp(double x){ if(fab

【习题整理】计算几何基础

bzoj1074[Scoi2007]折纸 思路:考虑倒着做,每次将在折叠的直线右边的扔掉,左边的点再对称一次加入: 算几知识:求向量关于法向量的对称向量 点$A$关于点$B$对称的点$C = 2B - A$ 如果要求$\vec{A}$关于法向量$\vec{l}$的对称向量$\vec{A'}$: 可以考虑都平移到原点 利用点积求出$\vec{A}$在$\vec{l}$上的投影点$D$, 再将点$A$关于$D$对称到$A'$: $A'$的坐标就是向量$\vec{A'}$ 1 #include<bit