内容参考书籍——《算法竞赛入门经典训练指南》

  在平面坐标系下,向量和点一样用两个数,x和y表示。判断相等使用“三态函数”dcmp,减少精度问题。另外,向量有一个所谓的“极角”,即从x轴正半轴旋转到该方向所需的角度。c标准库里的atan2函数就是用来求极角的,例如:向量(x,y)的极角就是atan2(y,x)(单位:弧度)。

  点积,高中知识。

  叉积。简单地说,两个向量的叉积等于两个向量组成的三角形的有向面积的两倍。(图中带箭头的向量为v,和v同一个起点的另外一条向量为w,忘记标v和w了尴尬)

cross(v,w)>0                   cross(v,w)<0 

  顺着第一个向量v看,,如果w在左边,那么v和w的叉积大于0,否则小于0.如果两个向量共线(方向相同),那么叉积等于0(三角形退化成为线段)。不难发现,叉积不满足交换律。事实上,cross(v,w)=-cross(w,v)。在坐标系下,两个向量的叉积等于xAyB-xByA。

  位置。当我们把叉积和点积组合在一起时,我们便可以细致地判断两个向量的位置关系。第一个向量v总是水平向右的,那么另外一个点就可以用这样的方式确定位置关系(点积符号,叉积符号)。例如,当w在第二象限时点积为负但叉积均为正,用(-,+)表示。

  旋转。向量可以绕起点旋转,公式为x= xcosa-ysina , y= xsina+ycosa。其中a为逆时针旋转的角。

  单位法线。旋转90°后把长度归一化即可。

  以上内容采用如下代码实现:

 1 struct Point
 2 {
 3     double x,y;
 4     Point(double x=0, double y=0):x(x),y(y) {}//构造函数,方便编写代码
 5 };
 6 typedef Point Vector;//别名
 7 //向量+向量=向量,点+向量=点
 8 Vector operator + (Vector A, Vector B){return Vector(A.x+B.x,A.y+B.y);}
 9 //点-点=向量
10 Vector operator - (Vector A, Vector B){return Vector(A.x-B.x,A.y-B.y);}
11 //向量*数=向量
12 Vector operator * (Vector A, double p){return Vector(A.x*p,A.y*p);}
13 //向量/数=向量
14 Vector operator / (Vector A, double p){return Vector(A.x/p,A.y/p);}
15
16 bool operator < (const Point& a, const Point& b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
17
18 const double eps = 1e-10;
19 int dcmp(double x)
20 {
21     if (fabs(x) < eps) return 0;
22     else return x < 0 ? -1 : 1;
23 }
24
25 bool operator == (const Point& a, const Point &b){return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;}
26
27 //计算点积、向量长度、夹角函数
28 double Dot(Vector A, Vector B){return A.x*B.x+A.y*B.y;}
29 double Length(Vector A){return sqrt(Dot(A,A));}
30 double Angle(Vector A, Vector B){return acos(Dot(A,B)/Length(A)/Length(B));}
31
32 //计算叉积
33 double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}
34 double Area2(Point A, Point B, Point C){return Cross(B-A,C-A);}
35
36 //计算旋转和单位法向量
37 //rad为弧度
38 Vector Rotate(Vector A, double rad){return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));}
39 Vector Normal(Vector A)
40 {
41     double L =Length(A);
42     return Vector(-A.y/L,A.x/L);
43 }

  下面是2019.9.24更新

  点和直线。采用参数方程表示直线(参数方程在表示直线,线段,射线时其方程的区别仅仅在于参数,射线t>0,线段在0-1之间,直线无限制) 。直线用直线上一点P0和方向向量v表示,则直线上所有点P满足P=P0+tv,其中t为参数。如果已知直线上两不同点A和B,则方向向量为B-A,所以参数方程为A+(B-A)t。

  直线交点。设直线为P+tv和Q+tw,设向量u=P-Q,交点在第一条直线的参数为t1,在第二条直线上的参数为t2,则交点的x和y可以列出一个方程,解得:

\[{t_1} = \frac{{cross\left( {w,u} \right)}}{{cross\left( {v,w} \right)}},\quad {t_2} = \frac{{cross\left( {v,u} \right)}}{{cross\left( {v,w} \right)}}\]

此处需要注意的是,从上述公式可以看到在精度要求极高的情况下需要自定义分数类。

  点到直线的距离。利用叉积计算,即平行四边形的面积除以底。

  点到线段的距离。分两种可能:该点的投影在线段上和不在线段上。若P点的投影在线段(AB)上(Q)则距离为PQ;若不在线段上,则所求距离为PA否则为PB。判断Q的位置可以用前文提到的(点积符号,叉积符号)进行判断。

  点的投影。尽管上面的方法避免了求投影点Q,但是有些时候我们不得不求出投影点Q。为此,我们把直线AB写成参数式A+tv(v为向量AB),并且设Q的参数为t0,那么Q=A+t0v,接下来解出t0就能得到Q点,根据PQ垂直于AB,两个向量的点积应该为0,因此Dot(v,P-(A+t0v))=0。根据分配律,有:Dot(v,P-A)-t0*Dot(v,v)=0,这样便解出t0,从而得到Q点。

  线段相交。判定两线段是否相交,我们定义“相交规范”为两线段恰好有一个公共点,且不在任何一条线段的端点。其充要条件为:每条线段的两个端点都在另一条线段的两侧(这里的“两侧”是指叉积的符号不同)。

  如果允许在端点处相交呢?那么,情况就比较复杂了,c1和c2不都是0,表示两线段共线,这时可能还会出现部分重叠的情况哦~如果c1和c2不都是0,则只有一种相交方法,即某个端点在另外一条线段上。为了判断上述情况是否发生,还需要判断一个点是否在一条线段上(不包含端点)。

  多边形有向面积。如果多边形是凸的,可以从第一个顶点出发,把凸多边形分成n-2个三角形,然后把面积加起来。事实上这个方法对非凸多边形也适用,因为三角形的面积是有向的,在外面的部分可以正负抵消。

  取P[0]点为划分顶点,一方面可以少算两个叉积(0和任意向量的叉积都等于0),另一方面也减少了乘法溢出的可能性,还不用特殊处理(i=n-1的时候,下一个顶点是P[0]而不是P[n],因为P[n]不存在)。

  以上内容代码如下:

转载于:https://www.cnblogs.com/125418a/p/11575865.html

计算几何--二维几何前置基础知识相关推荐

  1. python中如何将字典直接变成二维数组_python基础知识(列表、字典、二维数组)...

    记得改参数!!! (1)简述列表(list)结构的特点. List(列表) List的元素以线性方式存储,可以存放重复对象,List主要有以下两个实现类: ArrayList : 长度可变的数组,可以 ...

  2. python产生二维复数_Python基础知识大汇总--从放弃到入门

    1.python版本选择 初学python的同学,你可能知道有python2或者python3两个不同的版本,有些较老的视频或者较旧的文档还在推崇python2,认为python2比较稳定,很多公司都 ...

  3. 搬砖篇--002 几何入门基础知识

    几何入门基础知识 一. ξ\xiξ 多边形内角和外角和 二. ξ\xiξ 圆周角与圆心角 三. ξ\xiξ 相似与全等三角形 一. ξ\xiξ 多边形内角和外角和 1.观察下图所示,通过线性平移 ,可 ...

  4. #第六章 曲率二维表达的拟合应用 ​一、四维时空曲率的二维几何表达

    这又是一个麻烦的研究方向,四维影响的曲率一般都是通过函数计算出来的结果,如何在二维的几何平面直接用几何的方法表达这个曲率影响呢?不知道有多少人想过这么"无聊"的问题.笔者利用波的向 ...

  5. 计算机java语言教程,计算机JAVA教程二讲Java语言基础知识.doc

    计算机JAVA教程二讲Java语言基础知识 2.1简单数据类型 2.1.1 标识符和保留字 1.标识符 程序员对程序中的各个元素加以命名时使用的命名记号称为标识符(identifier).Java语言 ...

  6. OpenCASCADE:Modeling Data之二维几何

    OpenCASCADE:Modeling Data之二维几何 Geom2d包定义了 2dspace 中的几何对象.所有几何实体都经过 STEP 处理.对象通过引用处理. 特别是,Geom2d包提供了以 ...

  7. 超详细的Java面试题总结(二)之Java基础知识篇

    系列文章: 超详细的Java面试题总结(一)之Java基本知识 超详细的Java面试题总结(二)之Java基础知识篇 超详细的Java面试题总结(三)之Java集合篇常见问题 超详细的Java面试题总 ...

  8. java定义一个接口shape_java声明一个接口Shape2D用来实现二维几何形状类Circle和Rectangle。...

    java声明一个接口Shape2D用来实现二维几何形状类Circle和Rectangle.10 匿名网友2015.05.20浏览371次分享举报 1.声明一个接口Shape2D用来实现二维几何形状类C ...

  9. TCP/IP协议(二)tcp/ip基础知识

    转载:http://www.cnblogs.com/imyalost/p/6139191.html 一.TCP/IP的标准化 1.TCP/IP的含义 一般来说,TCP/IP是利用IP进行通信时所必须用 ...

最新文章

  1. PAT 显示格式错误
  2. 爱奇艺谢丹铭:用AI让创作者提升效率,让消费者简单快乐丨MEET2021
  3. 现在还有必要学Java开发吗?前景好吗?
  4. 注意!这些行为将会影响征信
  5. nodejs: mkdirs 递归创建目录
  6. mysql多表添加怎么写_mysql多表连接的几种写法
  7. php function函数用法,js的function函数是什么?js中function的用法
  8. python json是什么_python的json用法
  9. java动画api_使用MMAPI播放gif动画
  10. MPLS LDP邻居建立
  11. Android04-UI01常用控件
  12. Hyperledger Fabric教程(14)--动态添加组织的步骤
  13. typeof, offsetof, container_of宏
  14. 自己动手编写一个VS插件(三)——创建工具栏之一
  15. linux中硬盘安装教程图解,硬盘安装Debian 5教程图解
  16. SAP 货物移动相关Bapi
  17. [任务书+论文+PPT+源码]基于Android与多媒体的英文学习APP的设计与实现
  18. matlab函数merge_MATLAB数据合并方法
  19. 开源免费OA办公系统 帮助企业信息化建设
  20. Oracle查看硬解析

热门文章

  1. python调整屏幕缩放比例_python实现批量按比例缩放图片效果
  2. linux下spark的python编辑_Linux下搭建Spark 的 Python 编程环境的方法
  3. sqllite开发安卓项目_苹果安卓合作了?两大巨头共同居然共同开发这个项目
  4. idea如何给oracle添加数据_intelij idea下使用java和JDBC连接oracle数据库及简单的SQL操作...
  5. 苹果备忘录怎么调字体大小_苹果手机的备忘录怎么恢复?不知道的快来看看
  6. Python基础(函数)
  7. 硬盘、服务器、RAID磁盘阵列
  8. 基于容器实现高并发网站
  9. Java集合源码学习(4)HashSet
  10. 超全面的的常用RAID详解