// 此博文为迁移而来,写于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——三维几何(这玩意儿前提是我能搞懂= =)

[知识点]计算几何I——基础知识与多边形面积的更多相关文章

  1. Java 面试知识点解析(一)——基础知识篇

    前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...

  2. 大数据基础知识问答----spark篇,大数据生态圈

    Spark相关知识点 1.Spark基础知识 1.Spark是什么? UCBerkeley AMPlab所开源的类HadoopMapReduce的通用的并行计算框架 dfsSpark基于mapredu ...

  3. python 爬虫基础知识一

    网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本. 网络爬虫必备知识点 1. Python基础知识2. P ...

  4. hdu 2528:Area(计算几何,求线段与直线交点 + 求多边形面积)

    Area Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  5. HDU 2036 改革春风吹满地【计算几何/叉乘求多边形面积】

    改革春风吹满地 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  6. EOJ 1127. 多边形面积(计算几何)

    题目链接:1127. 多边形面积(计算几何) 题意 按逆时针顺序给出 \(n\) 个点的坐标,求这些点围成的多边形的面积. 思路 选择多边形上的一个点,然后每次枚举之后的两个点,计算叉积,注意要保留符 ...

  7. 「Java面试题/知识点精华集」20000+字的Java基础知识篇(2020最新版) !

    本文已经收录进我的 79K Star 的 Java 开源项目 JavaGuide:https://github.com/Snailclimb/JavaGuide (「Java学习+面试指南」一份涵盖大 ...

  8. 关于图计算&图学习的基础知识概览:前置知识点学习(Paddle Graph Learning (PGL))

    关于图计算&图学习的基础知识概览:前置知识点学习(Paddle Graph Learning (PGL)) 欢迎fork本项目原始链接:关于图计算&图学习的基础知识概览:前置知识点学习 ...

  9. poj 1654 Area(计算几何--叉积求多边形面积)

    一个简单的用叉积求任意多边形面积的题,并不难,但我却错了很多次,double的数据应该是要转化为long long,我转成了int...这里为了节省内存尽量不开数组,直接计算,我MLE了一发...,最 ...

随机推荐

  1. WPF样式

    <Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winf ...

  2. Gradle使用指南

    Gradle Plugin User Guide - Android Studio Project Sitehttp://tools.android.com/tech-docs/new-build-s ...

  3. Python 的三目运算

    其他语言:php 判定条件?为真时的结果:为假时的结果 $a=88 $b=99 $res = $a>$b?$a>$b 搞笑的Python:令人意想不到的语法形式 true_value if ...

  4. BZOJ1004 [HNOI2008]Cards(Polya计数)

    枚举每个置换,求在每个置换下着色不变的方法数,先求出每个循环的大小,再动态规划求得使用给定的颜色时对应的方法数. dp[i][j][k]表示处理到当前圈时R,B,G使用量为i,j,k时的方法数,背包思 ...

  5. Dwz下拉菜单的二级联动

    在DWZ文档中对组合框combox的是这样描述的: 在传统的select 用class 定义:class=”combox”, html 扩展:保留原有属性name,  增加了属性:ref. ref 属 ...

  6. loj 1257 (求树上每一个点到树上另一个点的最长距离)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1257 思路:首先需要用到一个知识点就是树上任一点到树上最长直径的某一个端点的距离最远, ...

  7. 安装PIL

    本来直接pip install PIL的,一直说找不到对应的版本,在廖雪峰老师的博客里发现原来PIL只更新到pytyon 2.7 后来就只有Pillow了,而我的版本是2.7.9 用的时候直接from ...

  8. RDS MySQL 全文检索相关问题的处理

    RDS MySQL 全文检索相关问题 1. RDS MySQL 对全文检索的支持 2. RDS MySQL 全文检索相关参数 3. RDS MySQL 全文检索中文支持 3.1 MyISAM 引擎表 ...

  9. 智能车学习(二)—— GPIO学习

    一.概述 使用的是蓝宇的底层,主要有初始化管脚,设置管脚状态,反转管脚状态等. 二.代码重述: 1.头文件gpio.h #ifndef GPIO_H //防止重复定义(gpio_H 开头) #defi ...

  10. DSP using MATLAB 示例Example3.4

    代码: n = [-1:3]; x = [1:5]; % x(n) = {1,2,3,4,5} % * % k = 0:500; w = (pi/500)*k; % [0,pi] axis divid ...