计算几何总结(Part 1~2)
Preface
对于一个初三连三角函数都不会的蒟蒻来说计算几何简直就是噩梦。
反正都是要学的也TM没办法,那就慢慢一点点学起吧。
计算几何要有正确的板子,不然那种几百行CODE的题写死你。
本蒟蒻的学习过程参考dalao's blog和lrj的蓝书
Part 1——基本结构命名与精度控制
首先计算几何就是在一个坐标系内搞来搞去的鬼畜东西,因此点是必不可少的
定义点,还是最普通的坐标表示法:
struct Point
{
DB x,y;
Point (DB X=0,DB Y=0) { x=X; y=Y; }
};
然后就是一个比较牛逼的东西了——向量,根据高中数学必修3上讲的,我们也使用坐标的方式表示一个向量。
说的请楚一点,因为我们知道可以用两个不共线的向量表示同一平面内的任意向量,因此我们把每一个向量\(\vec a\)都分解成\(x\vec i+y\vec j\)(\(\vec i,\vec j\)是单位向量)的形式并且\((x,y)\)就是这个向量的坐标。
由于都可以用坐标表示,我们就直接借用点的表示方法了。
typedef Point Vector;
然而计算几何中有一个不可避免的问题:精度,所以适当的控制精度还是很需要的。
因此我们手动搞一个\(EPS\),由我们熟知的:
- \(|a|<EPS \rightarrow a=0\)
- \(a<-EPS \rightarrow a<0\)
- \(a\ge EPS \rightarrow a>0\)
我们就可以写一个代码来判断一个数的零的关系(返回\(-1,0,1\))
inline int dcmp(DB x)
{
if (fabs(x)<EPS) return 0;
return x<-EPS?-1:1;
}
Part 2——点和向量之间的基本运算
一般运算符:
inline Vector operator + (Vector A,Vector B) { return Vector(A.x+B.x,A.y+B.y); }
inline Vector operator - (Point A,Point B) { return Vector(A.x-B.x,A.y-B.y); }
//inline Vector operator - (Vector A,Vector B) { return Vector(A.x-B.x,A.y-B.y); }
inline Vector operator * (Vector A,DB mul) { return Vector(A.x*mul,A.y*mul); }
inline Vector operator / (Vector A,DB div) { return Vector(A.x/div,A.y/div); }
注意一下:向量+向量=向量,点-点=向量(不过其实怎么定义都是一样的)
以及比较两个向量的运算符(个人习惯写在结构体里,这里的Point其实都是Vector的意思):
inline bool operator < (const Point A) const { return dcmp(x-A.x)?x<A.x:y<A.y; }
inline bool operator == (const Point A) const { return !dcmp(x-A.x)&&!dcmp(y-A.y); }
求一个向量的模长,即向量的长度:
inline DB Len(Vector A)
{
return sqrt(A.x*A.x+A.y*A.y);
}
求极角,这个直接用\(atan2(y,x)\)就可以求出\(\vec a(x,y)\)的极角了
inline DB Polar_Angle(Vector A)
{
return atan2(A.y,A.x);
}
点积,根据数学书上说的,\(\vec a \cdot\vec b\)的几何意义为\(\vec a\)在\(\vec b\)上的投影长度乘以\(\vec b\)的模长
用公式表述为:\(\vec a\cdot \vec b=|\vec a|\cdot |\vec b|\cdot \cos\ \theta\)(\(\theta\)为\(\vec a,\vec b\)之间的夹角)
在坐标表示下就是\(\vec a(x1,y1)\cdot \vec b(x2,y2)=x1\cdot x2+y1\cdot y2\)
inline DB Dot(Vector A,Vector B)
{
return A.x*B.x+A.y*B.y;
}
点积的应用有很多,以下列举一些常用的:
判断两个向量的前后(上下)关系
例如对于以下的向量\(\vec a\),如果另一个向量在红色区域时点积为正,在黄色区域时点积为负
判断两个向量是否垂直:\(\vec a \perp \vec b \Leftrightarrow \vec a \cdot \vec b=0\)
求两个向量的夹角,这个把点积的定义公式变形一下就好了:
inline DB Angle(Vector A,Vector B)
{
return acos(Dot(A,B)/Len(A)/Len(B));
}
求模长,这里可以用另一种方法求模长,即\(|\vec a|=\sqrt{(\vec a)^2}\):
inline DB Len(Vector A)
{
return sqrt(Dot(A,A));
}
向量的旋转,这个就是一个公式套上去
\(\vec a(x,y)\)可以看成是\(x\cdot(1,0)+y\cdot(0,1)\)(\((1,0)\)即为\(\vec i\),\((0,1)\)即为\(\vec j\))
分别旋转两个单位向量,则变成\(x\cdot(cos\ \theta,sin\ \theta)+y\cdot(-sin\ \theta,cos\ \theta)\)
inline Vector Rotate(Vector A,DB rad)
{
DB Cos=cos(rad),Sin=sin(rad);
return Vector(A.x*Cos-A.y*Sin,A.x*Sin+A.y*Cos);
}
法向量,与单位向量垂直的向量称为单位法向量,注意使用之前要判断这个向量是否为零
inline Vector Normal(Vector A)
{
DB l=Len(A); return Vector(-A.y/l,A.x/l);
}
叉积,又是根据数学书上说的,两个向量的叉积是一个标量,\(\vec a\times \vec b\)的几何意义为他们所形成的平行四边形的有向面积
注意面积是有向的,一个公式\(\vec a(x1,y1)\times \vec b(x2,y2)=x1\cdot y2-x2\cdot y1\)
inline DB Cross(Vector A,Vector B)
{
return A.x*B.y-A.y*B.x;
}
叉积的应用有很多,以下列举一些常用的:
判断两个向量的左右关系
例如对于以下的向量\(\vec a\),如果另一个向量在红色区域时叉积为正,在黄色区域时叉积为负
求三角形甚至是多边形的面积
求点到线段或者直线的距离
判断两个线段或者直线是否相交,并可以求交点
其它的很多东西,可以说叉积是整个计算几何的核心内容,这些我们下次再讲
Postscript
计算几何虽然以代码复杂,巨卡精度而闻名,但是学还是要学的不知道联赛考不考
争取近一个月都抽出点时间记录一下吧,接下来上Part1~2的所有模板CODE
#include<cstdio>
#include<cmath>
typedef double DB;
const DB EPS=1e-8;
inline int dcmp(DB x)
{
if (fabs(x)<EPS) return 0;
return x<-EPS?-1:1;
}
struct Point
{
DB x,y;
Point (DB X=0,DB Y=0) { x=X; y=Y; }
inline bool operator < (const Point A) const { return dcmp(x-A.x)?x<A.x:y<A.y; }
inline bool operator == (const Point A) const { return !dcmp(x-A.x)&&!dcmp(y-A.y); }
};
typedef Point Vector;
inline Vector operator + (Vector A,Vector B) { return Vector(A.x+B.x,A.y+B.y); }
inline Vector operator - (Point A,Point B) { return Vector(A.x-B.x,A.y-B.y); }
//inline Vector operator - (Vector A,Vector B) { return Vector(A.x-B.x,A.y-B.y); }
inline Vector operator * (Vector A,DB mul) { return Vector(A.x*mul,A.y*mul); }
inline Vector operator / (Vector A,DB div) { return Vector(A.x/div,A.y/div); }
inline DB Dot(Vector A,Vector B)
{
return A.x*B.x+A.y*B.y;
}
/*inline DB Len(Vector A)
{
return sqrt(A.x*A.x+A.y*A.y);
}*/
inline DB Len(Vector A)
{
return sqrt(Dot(A,A));
}
inline DB Cross(Vector A,Vector B)
{
return A.x*B.y-A.y*B.x;
}
inline DB Polar_Angle(Vector A)
{
return atan2(A.y,A.x);
}
inline DB Angle(Vector A,Vector B)
{
return acos(Dot(A,B)/Len(A)/Len(B));
}
inline Vector Rotate(Vector A,DB rad)
{
DB Cos=cos(rad),Sin=sin(rad);
return Vector(A.x*Cos-A.y*Sin,A.x*Sin+A.y*Cos);
}
inline Vector Normal(Vector A)
{
DB l=Len(A); return Vector(-A.y/l,A.x/l);
}
计算几何总结(Part 1~2)的更多相关文章
- ACM/ICPC 之 计算几何入门-叉积-to left test(POJ2318-POJ2398)
POJ2318 本题需要运用to left test不断判断点处于哪个分区,并统计分区的点个数(保证点不在边界和界外),用来做叉积入门题很合适 //计算几何-叉积入门题 //Time:157Ms Me ...
- HDU 2202 计算几何
最大三角形 Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- ACM 计算几何中的精度问题(转)
http://www.cnblogs.com/acsmile/archive/2011/05/09/2040918.html 计算几何头疼的地方一般在于代码量大和精度问题,代码量问题只要平时注意积累模 ...
- hdu 2393:Higher Math(计算几何,水题)
Higher Math Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- sdut 2603:Rescue The Princess(第四届山东省省赛原题,计算几何,向量旋转 + 向量交点)
Rescue The Princess Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 Several days ago, a b ...
- [知识点]计算几何I——基础知识与多边形面积
// 此博文为迁移而来,写于2015年4月9日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vxaq.html 1.前言 ...
- POJ 1106 Transmitters(计算几何)
题目链接 切计算几何,感觉计算几何的算法还不熟.此题,枚举线段和圆点的直线,平分一个圆 #include <iostream> #include <cstring> #incl ...
- TYVJ计算几何
今天讲了计算几何,发几道水水的tyvj上的题解... 计算几何好难啊!@Mrs.General....怎么办.... 这几道题都是在省选之前做的,所以前面的Point运算啊,dcmp啊,什么什么的,基 ...
- 计算几何 平面最近点对 nlogn分治算法 求平面中距离最近的两点
平面最近点对,即平面中距离最近的两点 分治算法: int SOLVE(int left,int right)//求解点集中区间[left,right]中的最近点对 { double ans; //an ...
- ZOJ 3157 Weapon --计算几何+树状数组
题意:给一些直线,问这些直线在直线x=L,x=R之间有多少个交点. 讲解见此文:http://blog.sina.com.cn/s/blog_778e7c6e0100q64a.html 首先将直线分别 ...
随机推荐
- Lucene创建索引流程
1.创建索引流程 原始文档:互联网上的网页(爬虫或蜘蛛).数据库中的数据.磁盘上的文件 创建文档对象(非结构化数据) 文档对象中的属性不叫属性现在成为域. 每个 Document 可以有多个 Fiel ...
- Access删除某一字段重复的数据但是要保留一条
如下图所示,Checktime这个字段有很多重复数据,我需要把所有Checktime这个字段重复的都删掉,但是还需要保留一条: 在Access做删除查询怎么做呀,来个Access高手,复制粘贴党请手下 ...
- 洗礼灵魂,修炼python(18)--温故加知新
类型转换: 1.str(),repr(),format():将非字符串数据转换为字符串 str():对象序列化的结果,相当于print输出 repr():程序中某个对象精确值 format():利用特 ...
- 洗礼灵魂,修炼python(16)--列表进阶话题—>上节作业讲解+copy模块,浅拷贝,深拷贝
上节课后作业: 1.使用列表解析输出结果:[(0,0),(0,2),(2,0),(2,2)] 方法1: 方法2: 方法3: 2.使用列表生成器打印斐波那契数列 3.使用列表解析生成列表[1x2,3x4 ...
- python第六十八天--第十二周作业
主题: 需求: 用户角色,讲师\学员, 用户登陆后根据角色不同,能做的事情不同,分别如下讲师视图 管理班级,可创建班级,根据学员qq号把学员加入班级 可创建指定班级的上课纪录,注意一节上课纪录对应多条 ...
- windows服务器设置文件属性设置去掉隐藏已知文件类型的扩展名(即文件后缀名可见)
摘要: 1.文件后缀名不可见,系统运维过程容易发生同名不同后缀的文件操作混淆的情况 2.windows系统默认是文件后缀名不可见 3.所以需要更改一下配置. 4.操作步骤如下图: (1)点击组织-文件 ...
- iris数据集(.csv .txt)免费下载
我看CSDN下载的iris数据集都需要币,我愿意免费共享,希望下载后的朋友们给我留个言 分享iris数据集(供学习使用): 链接: https://pan.baidu.com/s/1Knsp7zn-C ...
- SQLite基本操作-----IOS(如有雷同,纯属巧合)
一.常用方法 sqlite3 *db, 数据库句柄,跟文件句柄FILE很类似 sqlite3_stmt *stmt, 这个相当于ODBC的Command对象,用于保存编译好 ...
- (转)Python网络爬虫实战:世纪佳缘爬取近6万条数据
又是一年双十一了,不知道从什么时候开始,双十一从“光棍节”变成了“双十一购物狂欢节”,最后一个属于单身狗的节日也成功被攻陷,成为了情侣们送礼物秀恩爱的节日. 翻着安静到死寂的聊天列表,我忽然惊醒,不行 ...
- 线程间的通信_多生产者多消费者问题_JDK1.5新特性_Lock
对于同步代码块,对于锁的操作是隐式的但是在JDK1.5之前的这种方法效率有点低,判断会很多,后面升级之后有新的解决方案 jdk1.5以后将同步和锁封装成了对象,并将操作锁的隐式方式定义到了该对象中,将 ...