// 此博文为迁移而来,写于2015年4月9日,不代表本人现在的观点与看法。原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vxaq.html
1、前言
数学在讲解析几何,现在了解一下信息学中的计算几何也是极好的,和解析几何几乎是相通的。前面的内容比较简单,甚至自己看看就行都不值得写篇文章了,但是为了后面的内容作铺垫还是写写好了。
本章节从头到尾没有去看过别人的博文,基本上都是看的刘汝佳的《算法竞赛入门经典训练指南》,所以很多讲解是原创,有误敬请指出。几何问题背景知识多,内容杂乱,有些地方容易混淆,大家细看。
2、建模
开始做几何问题之前,必须先要将一些定义写好。我们都知道,向量是有方向,大小的量,而点是坐标系上的一个个点(词穷了= =。)但是,在信息学里面的平面坐标系中,向量和点的定义是一致的——只有x,y两个变量。因为一个点就相当于把向量的起点平移到坐标原点之后的终点坐标。下面就是他们的定义:
----------------------------------------------------------------------------------------------------
struct point
{
double x,y;
point(double x=0,double y=0):x(x),y(y) {} // 构造函数,方便代码编写
};
typedef point vector; //从程序实现上看,vector只是point的别名
----------------------------------------------------------------------------------------------------
3、符号
有了向量的表示,如何计算?这里要用到运算符重载,重载+、-、*、/、<、==。如何写数学里面都学了吧,我就不详说了。大家只要注意一下dcmp的作用。
----------------------------------------------------------------------------------------------------
vector operator + (vector a,vector b) { return vector(a.x+b.x,a.y+b.y); }
vector operator - (point a,point b) { return vector(a.x-b.x,a.y-b.y); }
vector operator * (vector a,double num) { return vector(a.x*num,a.y*num); }
vector operator / (vector a,double num) { return vector(a.x/num,a.y/num); }
bool operator < (point a,point b) { if (a.x!=b.x) return (a.x
const double eps=1e-10;
int dcmp(double x) { if (abs(x)<0)?-1:1; } // abs函数为绝对值
bool operator == (vector a,vector b) { return ( dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0); }
----------------------------------------------------------------------------------------------------
dcmp函数的作用是什么?当两个值差距很小时,同样会返回相同,即返回0,用以避免精度问题带来的麻烦。
4、基本运算
1、点积(Dot)。向量a和b的点积等于两者长度的乘积乘上它们夹角的余弦。夹角为从a到b逆时针旋转的角。因此,当夹角大于90°时,点积为负。顺便写上如何求向量长度(Length)和夹角(Angle):
----------------------------------------------------------------------------------------------------
double Dot(vector a,vector b) { return a.x*b.x+a.y*b.y; }
double Length(vector a) { return sqrt(Dot(a,a)); }
double Angle(vector a,vector b) { return acos(Dot(a,b)/Length(a)/Length(b)); } // acos为反余弦,全称arccos
----------------------------------------------------------------------------------------------------
2、叉积(Cross)。数学里暂时没学,但是作用非常大!后面的面积都需要用到它,我开始看的时候还半天没看懂。两个向量a和b的叉积等于a和b组成的三角形的有向面积的两倍。有向面积的概念是,朝着向量a看,如果向量b在你左边,则叉积大于0;如果在你右边,则小于0。

// 标准图已丢失
如上图所示,Cross(a,b)>0,且它的值为灰色阴影部分的面积。
----------------------------------------------------------------------------------------------------
double Cross(vector a,vector b) { return a.x*b.y-a.y*b.x; } // 叉积
double Area2(point a,point b,point c) { return Cross(b-a,c-a); } // 由a,b,c三个点构成的平行四边形面积
----------------------------------------------------------------------------------------------------
根据上述的点积,叉积的公式以及作用,我们可以比较方便的得到两个向量的位置关系:

括号里第一个数是点积,第二个数是叉积。设向量a水平向右,根据向量a,b的点积叉积的正负零情况,可以得到向量b的大致方向。这在以后将有很大的作用。
5、直线
在数学里面,我们已经学了直线的多种表达方式——两点式,一般式等等,信息学里面采用参数式方程。任何一条直线可以用该直线上一点P0和方向向量v表示,则直线上所有点P满足P=P0+tv,t是一个参数。则直线的参数式为: P=P0+tv
1、直线交点(lineIntersection)。设两条直线分别为P+t1v和Q+t2w,设向量u=P-Q,则可以得到:
----------------------------------------------------------------------------------------------------
point lineIntersection(point p,vector v,point q,vector w)
{
vector u=p-q;
double t=Cross(w,u)/Cross(v,w);
return p+v*t;
}
----------------------------------------------------------------------------------------------------
2、点到直线的距离(Point to line)。很简单,直接用叉积即平行四边形的面积除以底边就可得到。
----------------------------------------------------------------------------------------------------
double Distance_PTL(point x,point a,point b)
{
vector v1=a-x,v2=b-x;
return (abs(Cross(v1,v2)/Length(v1)));
}
----------------------------------------------------------------------------------------------------
3、点到线段的距离(Point to segement)。注意是线段!也就是说,如果点到线段所在直线的垂线并不在线段上,那么点到线段的距离并不是直接和到直线的距离一样(很拗口,慢慢看)。设投影点为Q,如果在线段AB上,即为P到直线AB的距离;如果在射线BA上,则所求距离为PA;否则为PB。如何判断Q的位置?如下图:
前面我们讲了利用点积叉积来判断两个向量的方向,这个地方就可以用到了。大家可以自己去试试v1,v2,v3之间的点积关系能够说明什么。
----------------------------------------------------------------------------------------------------
double Distance_PTS(point x,point a,point b)
{
if (a==b) return Length(x-a);
vector v1=b-a,v2=x-a,v3=x-b;
if (dcmp(Dot(v1,v2))<0) return Length(v2); // q在射线ba上
else if (dcmp(Dot(v1,v3))>0) return Length(v3); // q在射线ab上
else return fabs(Cross(v1,v2)/Length(v1)); // q在线段ab上
}
----------------------------------------------------------------------------------------------------
4、点在直线上的投影(lineProjection)。设AB的参数式为A+tv,P的投影点Q为Q=A+t0v,由于PQ⊥AB,则Dot(v,P-(A+t0v))=0,即Dot(v,P-A)-t0×Dot(v,v)=0,解出t0=Dot(v,x-a)/Dot(v,v),带入参数式,得Q点。
----------------------------------------------------------------------------------------------------
point lineProjection(point x,point a,point b)
{
vector v=b-a;
return (a+v*(Dot(v,x-a)/Dot(v,v)));
}
----------------------------------------------------------------------------------------------------
5、判断线段相交(Point to line)。判断条件:线段a的两个端点在线段b的两侧(即叉积符号不同)。
----------------------------------------------------------------------------------------------------
bool segmentIntersection(point a1,point a2,point b1,point b2)
{
double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1),c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1);
return (dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0);
}
----------------------------------------------------------------------------------------------------
6、多边形面积
将前面的知识全部铺垫好了,求多边形面积可以算是实战演练的第一步。求面积很简单,任取多边形的一个顶点(一般取读入的第一个顶点),从该点出发将多边形分成n-2个三角形,然后将面积加起来。
对于凸多边形来说,似乎比较好理解,如上图,S=S1+S2+S3+S4。凹多边形连接了每个顶点之后,可能会出现重叠面积和多边形以外的面积啊?可以确定的一点是,重叠面积=以外的面积(原因可以问你们数学老师)。所以无需顾虑,同样地,S=S1+S2+S3。
----------------------------------------------------------------------------------------------------
double polygonArea(point p[100],int n)
{
double area=0;
for (int i=1;i<=n-2;i++)
area+=Cross(p[i]-p[0],p[i+1]-p[0]);
return area/2;
}
----------------------------------------------------------------------------------------------------
7、总结
比较早就开始看这一章,但是搞了很久,主要是内容太杂了,搞得有点心烦。当然今天只讲了一些最基础的东西,后面将持续更新。
计算几何II——二维几何之凸包
计算几何III——二维几何之半平面交
计算几何IV——圆与圆的计算
计算几何V——三维几何(这玩意儿前提是我能搞懂= =)
- Java 面试知识点解析(一)——基础知识篇
前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...
- 大数据基础知识问答----spark篇,大数据生态圈
Spark相关知识点 1.Spark基础知识 1.Spark是什么? UCBerkeley AMPlab所开源的类HadoopMapReduce的通用的并行计算框架 dfsSpark基于mapredu ...
- python 爬虫基础知识一
网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本. 网络爬虫必备知识点 1. Python基础知识2. P ...
- hdu 2528:Area(计算几何,求线段与直线交点 + 求多边形面积)
Area Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- HDU 2036 改革春风吹满地【计算几何/叉乘求多边形面积】
改革春风吹满地 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Sub ...
- EOJ 1127. 多边形面积(计算几何)
题目链接:1127. 多边形面积(计算几何) 题意 按逆时针顺序给出 \(n\) 个点的坐标,求这些点围成的多边形的面积. 思路 选择多边形上的一个点,然后每次枚举之后的两个点,计算叉积,注意要保留符 ...
- 「Java面试题/知识点精华集」20000+字的Java基础知识篇(2020最新版) !
本文已经收录进我的 79K Star 的 Java 开源项目 JavaGuide:https://github.com/Snailclimb/JavaGuide (「Java学习+面试指南」一份涵盖大 ...
- 关于图计算&图学习的基础知识概览:前置知识点学习(Paddle Graph Learning (PGL))
关于图计算&图学习的基础知识概览:前置知识点学习(Paddle Graph Learning (PGL)) 欢迎fork本项目原始链接:关于图计算&图学习的基础知识概览:前置知识点学习 ...
- poj 1654 Area(计算几何--叉积求多边形面积)
一个简单的用叉积求任意多边形面积的题,并不难,但我却错了很多次,double的数据应该是要转化为long long,我转成了int...这里为了节省内存尽量不开数组,直接计算,我MLE了一发...,最 ...
随机推荐
- mysql TIME_WAIT
http://www.th7.cn/system/lin/201404/53762.shtml http://kerry.blog.51cto.com/172631/105233/ http://ww ...
- C#的初始化器
using System; using System.Collections; using System.Collections.Generic; using System.IO; using Sys ...
- Redis笔记(六)Redis的消息通知
Redis的消息通知可以使用List类型的LPUSH和RPOP(左进右出),当然更方便的是直接使用Redis的Pub/Sub(发布/订阅)模式. >>使用List实现队列 使用列表类型的L ...
- 【翻译四】java-并发之线程暂停
Pausing Execution with Sleep Thread.sleep causes the current thread to suspend execution for a speci ...
- makefile示例
1. 生成.so动态库 示例一: SoVer = 10010110CfgVer = 10010110 BinName = fnights.soGameName = "\"fnigh ...
- scala中的trait
这里的trait字面意思是特质或者特征,这个词翻译成特征比较合适.它的意义和java,c#中接口很类似.但是trait支持部分实现,也就是说可以在scala的trait中可以实现部分方法. 下面我们以 ...
- HTML - DOCTYPE
HTML - DOCTYPE HTML 5 doctype <!DOCTYPE html> HTML4.01 Based on SGML. so the browser need the ...
- 模板模式与策略模式/template模式与strategy模式/行为型模式
模板模式 模版模式,又被称为模版方法模式,它可以将工作流程进行封装,并且对外提供了个性化的控制,但主流程外界不能修改,也就是说,模版方法模式中,将工作的主体架构规定好,具体类可以根据自己的需要,各自去 ...
- Arduino101学习(一)——Windows下环境配置
一.Arduino IDE下载 要开发Arduino 101/Genuino 101,你需要先安装并配置好相应的开发环境.下载地址 http://www.arduino.cn/thread-5838- ...
- 系统剖析Android中的内存泄漏
[转发]作为Android开发人员,我们或多或少都听说过内存泄漏.那么何为内存泄漏,Android中的内存泄漏又是什么样子的呢,本文将简单概括的进行一些总结. 关于内存泄露的定义,我可以理解成这样 没 ...