计算几何算法概览.

合集下载

计算几何

计算几何

思考如下图形:
2020/2/6
9
先看最简单的多边形——三角形
2020/2/6
10
三角形的面积:
在解析几何里, △ABC的面积可以通过 如下方法求得:
点坐标 => 边长 => 海伦公式 => 面积
2020/2/6
11
思考:此方法的缺点:
计算量大 精度损失
更好的方法?
2020/2/6
12
31
2020/2/6
32
计算几何题的特点与做题要领
1.大部分不会很难,少部分题目思路很巧妙 2.做计算几何题目,模板很重要,模板必须高度可靠
。 3.要注意代码的组织,因为计算几何的题目很容易上
两百行代码,里面大部分是模板。如果代码一片混乱 ,那么会严重影响做题正确率。 4.注意精度控制。 5.能用整数的地方尽量用整数,要想到扩大数据的方 法(扩大一倍,或扩大sqrt2)。因为整数不用考虑浮 点误差,而且运算比浮点快。
2020/2/6
18
2020/2/6
19
2020/2/6
20
2020/2/6
21
2020/2/6
22
2020/2/6
23
2020/2/6
24
2020/2/6
25
2020/2/6
26
2020/2/6
27
2020/2/6
28
2020/2/6
29
2020/2/6
30
2020/2/6
形。
P3 P4
P2
P0
P1
P5 P6
设你种了很多树,想用一个篱笆把所有的
树都包在里面。出于经济考虑,这个篱笆应该是越 小越好。

geometric 几何算法

geometric 几何算法

geometric 几何算法(原创实用版)目录一、几何算法概述二、几何算法的应用领域三、几何算法的求解方法四、几何算法的优缺点分析五、几何算法的发展趋势正文一、几何算法概述几何算法,顾名思义,是研究几何问题的算法。

在计算机科学领域,几何算法主要研究如何使用计算机求解几何问题,例如计算两个图形的交集、计算多边形的面积等。

几何算法广泛应用于计算机图形学、计算机辅助设计、地理信息系统等领域。

二、几何算法的应用领域1.计算机图形学:在计算机图形学中,几何算法被用于生成、处理和显示图形。

例如,在三维图形学中,需要用到几何算法来计算物体的表面积、体积等。

2.计算机辅助设计:在计算机辅助设计(CAD)中,几何算法被用于创建、修改和分析工程图纸。

例如,在设计建筑结构时,需要用到几何算法来计算结构的稳定性和强度。

3.地理信息系统:在地理信息系统(GIS)中,几何算法被用于处理地理空间数据。

例如,在 GIS 中,需要用到几何算法来计算地理区域的面积、周长等。

三、几何算法的求解方法几何算法的求解方法有很多,下面介绍几种常见的方法:1.枚举法:对于一些简单的几何问题,可以采用枚举法求解。

例如,在计算多边形的面积时,可以枚举多边形的所有顶点,计算每个顶点对应的三角形面积,最后将所有三角形面积相加得到多边形的面积。

2.扫描线法:扫描线法是一种基于二维坐标系的几何算法。

它通过扫描线逐行扫描多边形,计算多边形与扫描线的交点,从而得到多边形的边界。

扫描线法可以高效地计算多边形的面积和周长。

3.空间分割法:空间分割法是一种基于空间数据的几何算法。

它通过将空间数据分成若干个区域,然后计算各个区域之间的交集,从而得到所需的几何信息。

空间分割法可以高效地处理复杂几何体。

四、几何算法的优缺点分析几何算法的优点:1.高效性:几何算法通常具有较高的计算效率,可以快速求解几何问题。

2.通用性:几何算法可以应用于多种几何问题,具有较强的通用性。

几何算法的缺点:1.复杂性:对于一些复杂的几何问题,几何算法的求解过程可能较为复杂,难以理解和实现。

计算几何算法概览

计算几何算法概览

计算几何算法概览一、引言计算机的出现使得很多原本十分繁琐的工作得以大幅度简化,但是也有一些在人们直观看来很容易的问题却需要拿出一套并不简单的通用解决方案,比如几何问题。

作为计算机科学的一个分支,计算几何主要研究解决几何问题的算法。

在现代工程和数学领域,计算几何在图形学、机器人技术、超大规模集成电路设计和统计等诸多领域有着十分重要的应用。

在本文中,我们将对计算几何常用的基本算法做一个全面的介绍,希望对您了解并应用计算几何的知识解决问题起到帮助。

二、目录本文整理的计算几何基本概念和常用算法包括如下内容:三、算法介绍如果一条线段的端点是有次序之分的,我们把这种线段成为有向线段(directed segment)。

如果有向线段p1p2的起点p1在坐标原点,我们可以把它称为矢量(vector)p2。

设二维矢量P=(x1,y1),Q=(x2,y2),则矢量加法定义为:P+Q=(x1+x2,y1+y2),同样的,矢量减法定义为:P-Q=(x1-x2,y1-y2)。

显然有性质P+Q=Q+P,P-Q=-(Q-P)。

计算矢量叉积是与直线和线段相关算法的核心部分。

设矢量P=(x1,y1),Q=(x2,y2),则矢量叉积定义为由(0,0)、p1、p2和p1+p2所组成的平行四边形的带符号的面积,即:P×Q=x1*y2-x2*y1,其结果是一个标量。

显然有性质P ×Q=-(Q×P)和P×(-Q)=-(P×Q)。

一般在不加说明的情况下,本文下述算法中所有的点都看作矢量,两点的加减法就是矢量相加减,而点的乘法则看作矢量叉积。

叉积的一个非常重要性质是可以通过它的符号判断两矢量相互之间的顺逆时针关系:若P×Q 0,则P在Q的顺时针方向。

若P×Q 0,则P在Q的逆时针方向。

若P×Q=0,则P与Q共线,但可能同向也可能反向。

折线段的拐向判断方法可以直接由矢量叉积的性质推出。

数学几何运算

数学几何运算

数学几何运算几何运算是数学中的一个重要分支,研究着数学空间内的图形形状、大小和位置关系。

几何运算可以帮助我们进行空间推导和问题解决。

本文将介绍数学几何运算的主要内容,包括点、线、面的运算。

1. 点的几何运算点是几何空间中最基本的元素,不具有大小和方向,只有位置。

点的几何运算主要包括点的坐标表示和点的平移变换。

1.1 点的坐标表示在数学中,我们通常使用笛卡尔坐标系来表示点的位置。

笛卡尔坐标系是一个二维平面上的直角坐标系,通过横坐标和纵坐标来确定点的位置。

例如,点A在坐标系中的位置可以表示为(Ax, Ay)。

1.2 点的平移变换点的平移变换是将点沿某个方向移动一定的距离。

平移变换可以通过将点的坐标分别增加或减少相同的值来实现。

例如,将点A(x, y)沿x轴正方向平移5个单位可以得到新的点A'(x+5, y)。

2. 线的几何运算线是由一系列点组成的几何对象,可以用来连接两个点或者定义一个方向。

线的几何运算主要包括线段的长度计算和线段的延长与截取。

2.1 线段的长度计算线段的长度是指线段所覆盖的距离。

可以使用两点间的距离公式来计算线段的长度。

例如,对于线段AB,长度可以表示为AB = √[(B x - Ax)² + (By - Ay)²]。

2.2 线段的延长与截取线段的延长是指在线段的某一端继续延伸线段的长度。

线段的截取是指将线段的一部分分离出来。

延长和截取线段可以通过改变线段的两个端点来实现。

3. 面的几何运算面是二维几何空间中的一个平面区域,由无数个点组成。

面的几何运算主要包括面积计算和面的旋转变换。

3.1 面积计算面的面积是指面覆盖的二维区域大小。

对于简单的几何图形(如矩形、三角形、圆等),可以使用相应的面积公式计算面积。

对于复杂的几何图形,可以将其分解为多个简单的几何图形,然后计算每个几何图形的面积,最后将它们相加。

3.2 面的旋转变换面的旋转变换是指将面绕着某一点或某一轴旋转一定的角度。

计算几何初步

计算几何初步

矢量的叉乘
矢量积的一般含义:两个矢量a 和b的矢量积是一 个矢量,记作a×b,其模等于由a 和b作成的平 行四边形的面积,方向与平行四边形所在平面垂 直,当站在这个方向观察时,a 逆时针转过一个 小于π的角到达 b 的方向。这个方向也可以用物 理上的右手螺旋定则判断:右手四指弯向由 A 转 到B 的方向(转过的角小于π),拇指指向的就 是矢量积的方向。
给定两个矢量: 和 ,对它们的公共端点P0 来说,判断 是否在 的顺时针方向。
如图,把 P0作为原点,得出向量P1’=P1-P0和 P2’=P2-P0,因此,这两个向量的叉积为(p1p0)×(p2-p0)= (x1-x0)(y2-y0)-(x2-x0)(y1-y0),如果该 叉积为正,则 在 的顺时针方向,如果为 负,则 在 的逆时针方向。如果等于 0, 则 P0,P1,P2三点共线。
探讨另一个重要问题
给定两个矢量 和 ,确定它们在点P1是向 左转还是向右转,即∠P0P1P2的转向。也就是说 确定连续线段是向左转还是向右转。
矢量的旋转
矢量的旋转:实际应用中,经常需要从一个矢量 转到另一个矢量,这个过程称为矢量的旋转,旋 转的方向由叉积判定。很多例子都用到矢量的旋 转这个方法和相应特性。
计算几何的内容及特点
矢量 基本算法 二维凸包 半平面交 最小圆覆盖 三维凸包 旋转卡壳 …..
代码量大 特殊情况多 精度问题难以控制 ……
需要注意的问题
不可直接判断相等(即使是那些看起来似乎“显 然”没有精度问题的值)
尽量只用加/减法和乘法,避免除法,尤其避免除 以一个很小的数
a的长度或模。记作a|。
夹角:两个非0矢量a、b,在空间任取一点O,

计算几何算法

计算几何算法

计算几何算法计算几何学是一门复杂而又深入的学科,它将数学和计算机科学结合在一起,用于对空间几何问题提出数学和计算机科学方法的解决方案。

计算几何学研究的主要内容包括几何计算、几何分析、图形处理等等。

计算几何学的研究可以追溯到古希腊的几何学,但它作为现代科学的一个分支是在20世纪60年代开始发展的。

在这50多年的发展中,计算几何学逐渐发展出一系列算法以解决各种几何问题。

计算几何学的算法分为基本算法和高级算法。

基本算法主要包括点位置检查算法、距离计算算法、可视性分析算法、图算法等等。

例如,点位置检查算法是一种用于判断两个点在三维空间中的关系的算法,距离计算算法用于计算两点在三维空间中的距离,可视性分析算法用于检测两个几何物体之间的可视性,而图算法则是用于建模空间结构和做几何计算的一类算法。

除了基本算法外,计算几何学还涉及一些高级算法,如几何建模算法、线性规划算法、最短路径算法、剖面分析算法等。

几何建模算法用于模拟物体的表面形状,利用该算法可以建立更真实的虚拟模型。

线性规划算法用于解决线性优化问题,可以用来找出最优路径。

最短路径算法用于求解具有权重的网络最短路径,是图论中应用最广泛的算法之一。

最后,剖面分析算法则是一种用于求解物体表面剖面的算法,可以帮助分析物体的结构和性质。

计算几何学的算法可以应用于各种空间几何问题的求解,为计算机视觉、图形学以及制造等领域提供了强大的算法支持。

计算几何学算法在空间几何问题领域中占据着重要的地位,在各种空间几何计算中得到了广泛的应用。

随着计算机技术的不断发展,计算几何学算法也在不断的完善和改进,使得计算几何学能够更加有效的解决空间几何问题,为解决现实世界中的各种复杂问题提供了强有力的技术支持。

展望未来,计算几何学将继续发展壮大,发展出更加强大的算法,为人类带来更多惊喜和机遇。

计算几何

计算几何

2.3.1 判断线段相交和求交点坐 标
判断线段相交和求线段交点是解决 几何问题的基础和基本手段
这两个操作在几何问题中大量应用
而判断线段是否相交是更常见的问 题,在很多情况下只是判断线段是否 相交,而不是求其交点
2.3.2 线段的规范相交和非规范 相交
(1)
(2)
(3)
(4)
(5)
(1)是规范相交,其它是非规范相交。非规范相交 的情况还有很多。通常只考虑规范相交
第11章 计算几何
1. 计算几何概述 2. 计算几何的基本问题 3. 凸包及其应用 4. 求线段集的两两交点
1. 计算几何概述
在计算机图形学、图形用户接口、可视化技术、计算机辅 助设计、模式识别等领域,需要快速的几何算法
解析几何是一个选择。解析几何把所有的几何问题转换成 纯粹的代数问题,而代数问题是可以用计算机解决的
2.6.1 多边形面积的计算公式
N 2
S S p1 pi1 pi2
P1 P6
i 1
N2 1

xi1 x1
i1 2 xi2 x1
yi1 y1 yi2 y1

N2 1 i1 2
x1 xi1 xi2
y1 1 yi1 1 yi2 1
P2 P3
2.4.2 多边形分类
如果多边形任意两条不相邻的边没有公共交点,则称这个多边 形为简单多边形;否则称为复杂多边形
但一类特殊的复杂多边形称为临界多边形,在性质上更接近于 简单多边形
P1
P7
P6
P2 P5
P4
P3
简单多边形
P4 P1
P3
P2
复杂多边形
P4 P2
P3

计算机图形学中计算几何算法

计算机图形学中计算几何算法

计算机图形学中计算几何算法/*计算几何(本文档源文件格式为.cpp,上传百度时被迫改有.txt) 目录㈠点的基本运算1. 平面上两点之间距离 12. 判断两点是否重合 13. 矢量叉乘 14. 矢量点乘 25. 判断点是否在线段上 26. 求一点饶某点旋转后的坐标 27. 求矢量夹角 2㈡线段及直线的基本运算1. 点与线段的关系 32. 求点到线段所在直线垂线的垂足 43. 点到线段的最近点 44. 点到线段所在直线的距离 45. 点到折线集的最近距离 46. 判断圆是否在多边形内 57. 求矢量夹角余弦 58. 求线段之间的夹角 59. 判断线段是否相交 610.判断线段是否相交但不交在端点处 611.求线段所在直线的方程 612.求直线的斜率 713.求直线的倾斜角 714.求点关于某直线的对称点 715.判断两条直线是否相交及求直线交点 716.判断线段是否相交,如果相交返回交点 7㈢多边形常用算法模块1. 判断多边形是否简单多边形 82. 检查多边形顶点的凸凹性 93. 判断多边形是否凸多边形 94. 求多边形面积 95. 判断多边形顶点的排列方向,方法一 106. 判断多边形顶点的排列方向,方法二 107. 射线法判断点是否在多边形内 108. 判断点是否在凸多边形内 119. 寻找点集的graham算法 1210.寻找点集凸包的卷包裹法 1311.判断线段是否在多边形内 1412.求简单多边形的重心 1513.求凸多边形的重心 1714.求肯定在给定多边形内的一个点 1715.求从多边形外一点出发到该多边形的切线 1816.判断多边形的核是否存在 19㈣圆的基本运算1 .点是否在圆内 202 .求不共线的三点所确定的圆 21㈤矩形的基本运算1.已知矩形三点坐标,求第4点坐标 22 ㈥常用算法的描述 22㈦补充1.两圆关系: 242.判断圆是否在矩形内: 243.点到平面的距离: 254.点是否在直线同侧: 255.镜面反射线: 256.矩形包含: 267.两圆交点: 278.两圆公共面积: 289. 圆和直线关系: 2910. 内切圆: 3011. 求切点: 3112. 线段的左右旋: 3113.公式: 32*//* 需要包含的头文件 */#include/* 常用的常量定义 */const double INF = 1E200const double EP = 1E-10const int MAXV = 300const double PI = 3.14159265/* 基本几何结构 */struct POINT{double x;double y;POINT(double a=0, double b=0) { x=a; y=b;} //constructor };struct LINESEG{POINT s;POINT e;LINESEG(POINT a, POINT b) { s=a; e=b;}LINESEG() { }};struct LINE // 直线的解析方程 a*x+b*y+c=0 为统一表示,约定a >= 0{double a;double b;double c;LINE(double d1=1, double d2=-1, double d3=0) {a=d1; b=d2; c=d3;}};/*********************** ** 点的基本运算 ** ***********************/double dist(POINT p1,POINT p2) // 返回两点之间欧氏距离{return( sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ) );}bool equal_point(POINT p1,POINT p2) // 判断两个点是否重合{return ( (abs(p1.x-p2.x)<ep)&&(abs(p1.y-p2.y)}/************************************************************** ****************r=multiply(sp,ep,op),得到(sp-op)和(ep-op)的叉积r>0:ep在矢量opsp的逆时针方向;r=0:opspep三点共线;r<0:ep在矢量opsp的顺时针方向*************************************************************** ****************/double multiply(POINT sp,POINT ep,POINT op){return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));}/*r=dotmultiply(p1,p2,op),得到矢量(p1-op)和(p2-op)的点积,如果两个矢量都非零矢量r<0:两矢量夹角为锐角;r=0:两矢量夹角为直角;r>0:两矢量夹角为钝角*************************************************************** ****************/double dotmultiply(POINT p1,POINT p2,POINT p0){return ((p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y));}/************************************************************** ****************判断点p是否在线段l上条件:(p在线段l所在的直线上) && (点p在以线段l为对角线的矩形内)*************************************************************** ****************/bool online(LINESEG l,POINT p){return( (multiply(l.e,p,l.s)==0) &&( ( (p.x-l.s.x)*(p.x-l.e.x)<=0 )&&( (p.y-l.s.y)*(p.y-l.e.y)<=0 ) ) );}// 返回点p以点o为圆心逆时针旋转alpha(单位:弧度)后所在的位置POINT rotate(POINT o,double alpha,POINT p){POINT tp;p.x-=o.x;p.y-=o.y;tp.x=p.x*cos(alpha)-p.y*sin(alpha)+o.x;tp.y=p.y*cos(alpha)+p.x*sin(alpha)+o.y;return tp;}/* 返回顶角在o点,起始边为os,终止边为oe的夹角(单位:弧度)角度小于pi,返回正值角度大于pi,返回负值可以用于求线段之间的夹角原理:r = dotmultiply(s,e,o) / (dist(o,s)*dist(o,e))r'= multiply(s,e,o)r >= 1 angle = 0;r <= -1 angle = -PI-1<r<="0">*/double angle(POINT o,POINT s,POINT e){double cosfi,fi,norm;double dsx = s.x - o.x;double dsy = s.y - o.y;double dex = e.x - o.x;double dey = e.y - o.y;cosfi=dsx*dex+dsy*dey;norm=(dsx*dsx+dsy*dsy)*(dex*dex+dey*dey);cosfi /= sqrt( norm );if (cosfi >= 1.0 ) return 0;if (cosfi <= -1.0 ) return -3.1415926;fi=acos(cosfi);if (dsx*dey-dsy*dex>0) return fi; // 说明矢量os 在矢量 oe的顺时针方向return -fi;}/*****************************\* ** 线段及直线的</r</r</ep)&&(abs(p1.y-p2.y)基本运算 ** *\*****************************//* 判断点与线段的关系,用途很广泛本函数是根据下面的公式写的,P是点C到线段AB所在直线的垂足AC dot ABr = ---------||AB||^2(Cx-Ax)(Bx-Ax) + (Cy-Ay)(By-Ay)= -------------------------------L^2r has the following meaning:r=0 P = Ar=1 P = Br<0 P is on the backward extension of ABr>1 P is on the forward extension of AB0<r*/double relation(POINT p,LINESEG l){LINESEG tl;tl.s=l.s;tl.e=p;return dotmultiply(tl.e,l.e,l.s)/(dist(l.s,l.e)*dist(l.s,l.e));}// 求点C到线段AB所在直线的垂足 PPOINT perpendicular(POINT p,LINESEG l){double r=relation(p,l);POINT tp;tp.x=l.s.x+r*(l.e.x-l.s.x);tp.y=l.s.y+r*(l.e.y-l.s.y);return tp;}/* 求点p到线段l的最短距离,并返回线段上距该点最近的点np 注意:np是线段l上到点p最近的点,不一定是垂足 */ double ptolinesegdist(POINT p,LINESEG l,POINT &np) {double r=relation(p,l);if(r<0){np=l.s;return dist(p,l.s);}if(r>1){np=l.e;return dist(p,l.e);}np=perpendicular(p,l);return dist(p,np);}// 求点p到线段l所在直线的距离,请注意本函数与上个函数的区别double ptoldist(POINT p,LINESEG l){return abs(multiply(p,l.e,l.s))/dist(l.s,l.e);}/* 计算点到折线集的最近距离,并返回最近点.注意:调用的是ptolineseg()函数 */double ptopointset(int vcount,POINT pointset[],POINT p,POINT &q){int i;double cd=double(INF),td;LINESEG l;POINT tq,cq;for(i=0;i{l.s=pointset[i];l.e=pointset[i+1];td=ptolinesegdist(p,l,tq);if(td{cd=td;cq=tq;}}q=cq;return cd;}/* 判断圆是否在多边形内.ptolineseg()函数的应用2 */bool CircleInsidePolygon(int vcount,POINT center,double radius,POINT polygon[]){POINT q;double d;q.x=0;q.y=0;d=ptopointset(vcount,polygon,center,q);if(d<radius||fabs(d-radius)return true;elsereturn false;}/* 返回两个矢量l1和l2的夹角的余弦(-1 --- 1)注意:如果想从余弦求夹角的话,注意反余弦函数的定义域是从 0到pi */double cosine(LINESEG l1,LINESEG l2){return (((l1.e.x-l1.s.x)*(l2.e.x-l2.s.x) +(l1.e.y-l1.s.y)*(l2.e.y-l2.s.y))/(dist(l1.e,l1.s)*dist(l2.e,l2.s))) );}// 返回线段l1与l2之间的夹角单位:弧度范围(-pi,pi)double lsangle(LINESEG l1,LINESEG l2){POINT o,s,e;o.x=o.y=0;s.x=l1.e.x-l1.s.x;s.y=l1.e.y-l1.s.y;e.x=l2.e.x-l2.s.x;e.y=l2.e.y-l2.s.y;return angle(o,s,e);}// 如果线段u和v相交(包括相</radius||fabs(d-radius)</r交在端点处)时,返回true////判断P1P2跨立Q1Q2的依据是:( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

计算几何算法概览[ 2001-03-23 ] 怒火之袍出处:放飞技术网计算机的出现使得很多原本十分繁琐的工作得以大幅度简化,但是也有一些在人们直观看来很容易的问题却需要拿出一套并不简单的通用解决方案,比如几何问题。

作为计算机科学的一个分支,计算几何主要研究解决几何问题的算法。

在现代工程和数学领域,计算几何在图形学、机器人技术、超大规模集成电路设计和统计等诸多领域有着十分重要的应用。

一、引言计算机的出现使得很多原本十分繁琐的工作得以大幅度简化,但是也有一些在人们直观看来很容易的问题却需要拿出一套并不简单的通用解决方案,比如几何问题。

作为计算机科学的一个分支,计算几何主要研究解决几何问题的算法。

在现代工程和数学领域,计算几何在图形学、机器人技术、超大规模集成电路设计和统计等诸多领域有着十分重要的应用。

在本文中,我们将对计算几何常用的基本算法做一个全面的介绍,希望对您了解并应用计算几何的知识解决问题起到帮助。

二、目录本文整理的计算几何基本概念和常用算法包括如下内容:1.矢量的概念2.矢量加减法3.矢量叉积4.折线段的拐向判断5.判断点是否在线段上6.判断两线段是否相交7.判断线段和直线是否相交8.判断矩形是否包含点9.判断线段、折线、多边形是否在矩形中10.判断矩形是否在矩形中11.判断圆是否在矩形中12.判断点是否在多边形中13.判断线段是否在多边形内14.判断折线是否在多边形内15.判断多边形是否在多边形内16.判断矩形是否在多边形内17.判断圆是否在多边形内18.判断点是否在圆内19.判断线段、折线、矩形、多边形是否在圆内20.判断圆是否在圆内21.计算点到线段的最近点22.计算点到折线、矩形、多边形的最近点23.计算点到圆的最近距离及交点坐标24.计算两条共线的线段的交点25.计算线段或直线与线段的交点26.求线段或直线与折线、矩形、多边形的交点27.求线段或直线与圆的交点28.凸包的概念29.凸包的求法三、算法介绍矢量的概念:如果一条线段的端点是有次序之分的,我们把这种线段成为有向线段(directed segment)。

如果有向线段p1p2的起点p1在坐标原点,我们可以把它称为矢量(vector)p2。

矢量加减法:设二维矢量P = ( x1, y1 ),Q = ( x2 , y2 ),则矢量加法定义为:P + Q = ( x1 + x2 , y1 + y2 ),同样的,矢量减法定义为:P - Q = ( x1 - x2 , y1 - y2 )。

显然有性质P + Q = Q + P,P - Q = - ( Q - P )。

矢量叉积:计算矢量叉积是与直线和线段相关算法的核心部分。

设矢量P = ( x1, y1 ),Q = ( x2, y2 ),则矢量叉积定义为由(0,0)、p1、p2和p1+p2所组成的平行四边形的带符号的面积,即:P ×Q = x1*y2 - x2*y1,其结果是一个标量。

显然有性质P ×Q = - ( Q ×P ) 和P ×( - Q ) = - ( P ×Q )。

一般在不加说明的情况下,本文下述算法中所有的点都看作矢量,两点的加减法就是矢量相加减,而点的乘法则看作矢量叉积。

叉积的一个非常重要性质是可以通过它的符号判断两矢量相互之间的顺逆时针关系:若P ×Q > 0 , 则P在Q的顺时针方向。

若P ×Q < 0 , 则P在Q的逆时针方向。

若P ×Q = 0 , 则P与Q共线,但可能同向也可能反向。

折线段的拐向判断:折线段的拐向判断方法可以直接由矢量叉积的性质推出。

对于有公共端点的线段p0p1和p1p2,通过计算(p2 - p0) ×(p1 - p0)的符号便可以确定折线段的拐向:若(p2 - p0) ×(p1 - p0) > 0,则p0p1在p1点拐向右侧后得到p1p2。

若(p2 - p0) ×(p1 - p0) < 0,则p0p1在p1点拐向左侧后得到p1p2。

若(p2 - p0) ×(p1 - p0) = 0,则p0、p1、p2三点共线。

具体情况可参照下图:判断点是否在线段上:设点为Q,线段为P1P2 ,判断点Q在该线段上的依据是:( Q - P1 ) ×( P2 - P1 ) = 0 且Q 在以P1,P2为对角顶点的矩形内。

前者保证Q点在直线P1P2上,后者是保证Q点不在线段P1P2的延长线或反向延长线上,对于这一步骤的判断可以用以下过程实现:ON-SEGMENT(pi,pj,pk)if min(xi,xj) <= xk <= max(xi,xj) and min(yi,yj) <= yk <= max(yi,yj)then return true;else return false;特别要注意的是,由于需要考虑水平线段和垂直线段两种特殊情况,min(xi,xj)<=xk<=max(xi,xj)和min(yi,yj)<=yk<=max(yi,yj)两个条件必须同时满足才能返回真值。

判断两线段是否相交:我们分两步确定两条线段是否相交:(1)快速排斥试验设以线段P1P2 为对角线的矩形为R,设以线段Q1Q2 为对角线的矩形为T,如果R 和T不相交,显然两线段不会相交。

(2)跨立试验如果两线段相交,则两线段必然相互跨立对方。

若P1P2跨立Q1Q2 ,则矢量( P1 - Q1 ) 和( P2 - Q1 )位于矢量( Q2 - Q1 ) 的两侧,即( P1 - Q1 ) ×( Q2 - Q1 ) * ( P2 - Q1 ) ×( Q2 - Q1 ) < 0。

上式可改写成( P1 - Q1 ) ×( Q2 - Q1 ) * ( Q2 - Q1 ) ×( P2 - Q1 ) > 0。

当( P1 - Q1 ) ×( Q2 - Q1 ) = 0 时,说明( P1 - Q1 ) 和( Q2 - Q1 )共线,但是因为已经通过快速排斥试验,所以P1 一定在线段Q1Q2上;同理,( Q2 - Q1 ) ×(P2 - Q1 ) = 0 说明P2 一定在线段Q1Q2上。

所以判断P1P2跨立Q1Q2的依据是:( P1 - Q1 ) ×( Q2 - Q1 ) * ( Q2 - Q1 ) ×( P2 - Q1 ) >= 0。

同理判断Q1Q2跨立P1P2的依据是:( Q1 - P1 ) ×( P2 - P1 ) * ( P2 - P1 ) ×( Q2 - P1 ) >= 0。

具体情况如下图所示:在相同的原理下,对此算法的具体的实现细节可能会与此有所不同,除了这种过程外,大家也可以参考《算法导论》上的实现。

判断线段和直线是否相交:有了上面的基础,这个算法就很容易了。

如果线段P1P2和直线Q1Q2相交,则P1P2跨立Q1Q2,即:( P1 - Q1 ) ×( Q2 - Q1 ) * ( Q2 - Q1 ) ×( P2 - Q1 ) >= 0。

判断矩形是否包含点:只要判断该点的横坐标和纵坐标是否夹在矩形的左右边和上下边之间。

判断线段、折线、多边形是否在矩形中:因为矩形是个凸集,所以只要判断所有端点是否都在矩形中就可以了。

判断矩形是否在矩形中:只要比较左右边界和上下边界就可以了。

判断圆是否在矩形中:很容易证明,圆在矩形中的充要条件是:圆心在矩形中且圆的半径小于等于圆心到矩形四边的距离的最小值。

判断点是否在多边形中:判断点P是否在多边形中是计算几何中一个非常基本但是十分重要的算法。

以点P为端点,向左方作射线L,由于多边形是有界的,所以射线L的左端一定在多边形外,考虑沿着L从无穷远处开始自左向右移动,遇到和多边形的第一个交点的时候,进入到了多边形的内部,遇到第二个交点的时候,离开了多边形,……所以很容易看出当L和多边形的交点数目C是奇数的时候,P在多边形内,是偶数的话P在多边形外。

但是有些特殊情况要加以考虑。

如图下图(a)(b)(c)(d)所示。

在图(a)中,L和多边形的顶点相交,这时候交点只能计算一个;在图(b)中,L和多边形顶点的交点不应被计算;在图(c)和(d) 中,L和多边形的一条边重合,这条边应该被忽略不计。

如果L和多边形的一条边重合,这条边应该被忽略不计。

为了统一起见,我们在计算射线L和多边形的交点的时候,1。

对于多边形的水平边不作考虑;2。

对于多边形的顶点和L相交的情况,如果该顶点是其所属的边上纵坐标较大的顶点,则计数,否则忽略;3。

对于P在多边形边上的情形,直接可判断P属于多边行。

由此得出算法的伪代码如下:count ←0;以P为端点,作从右向左的射线L;for 多边形的每条边sdo if P在边s上then return true;if s不是水平的then if s的一个端点在L上if 该端点是s两端点中纵坐标较大的端点then count ←count+1else if s和L相交then count ←count+1;if count mod 2 = 1then return true;else return false;其中做射线L的方法是:设P'的纵坐标和P相同,横坐标为正无穷大(很大的一个正数),则P和P'就确定了射线L。

判断点是否在多边形中的这个算法的时间复杂度为O(n)。

另外还有一种算法是用带符号的三角形面积之和与多边形面积进行比较,这种算法由于使用浮点数运算所以会带来一定误差,不推荐大家使用。

判断线段是否在多边形内:线段在多边形内的一个必要条件是线段的两个端点都在多边形内,但由于多边形可能为凹,所以这不能成为判断的充分条件。

如果线段和多边形的某条边内交(两线段内交是指两线段相交且交点不在两线段的端点),因为多边形的边的左右两侧分属多边形内外不同部分,所以线段一定会有一部分在多边形外(见图a)。

于是我们得到线段在多边形内的第二个必要条件:线段和多边形的所有边都不内交。

线段和多边形交于线段的两端点并不会影响线段是否在多边形内;但是如果多边形的某个顶点和线段相交,还必须判断两相邻交点之间的线段是否包含于多边形内部(反例见图b)。

因此我们可以先求出所有和线段相交的多边形的顶点,然后按照X-Y坐标排序(X坐标小的排在前面,对于X坐标相同的点,Y坐标小的排在前面,这种排序准则也是为了保证水平和垂直情况的判断正确),这样相邻的两个点就是在线段上相邻的两交点,如果任意相邻两点的中点也在多边形内,则该线段一定在多边形内。

相关文档
最新文档