计算几何与图形学有关的几种常用算法
- 格式:doc
- 大小:169.50 KB
- 文档页数:20
geometric 几何算法(原创实用版)目录一、几何算法概述二、几何算法的应用领域三、几何算法的求解方法四、几何算法的优缺点分析五、几何算法的发展趋势正文一、几何算法概述几何算法,顾名思义,是研究几何问题的算法。
在计算机科学领域,几何算法主要研究如何使用计算机求解几何问题,例如计算两个图形的交集、计算多边形的面积等。
几何算法广泛应用于计算机图形学、计算机辅助设计、地理信息系统等领域。
二、几何算法的应用领域1.计算机图形学:在计算机图形学中,几何算法被用于生成、处理和显示图形。
例如,在三维图形学中,需要用到几何算法来计算物体的表面积、体积等。
2.计算机辅助设计:在计算机辅助设计(CAD)中,几何算法被用于创建、修改和分析工程图纸。
例如,在设计建筑结构时,需要用到几何算法来计算结构的稳定性和强度。
3.地理信息系统:在地理信息系统(GIS)中,几何算法被用于处理地理空间数据。
例如,在 GIS 中,需要用到几何算法来计算地理区域的面积、周长等。
三、几何算法的求解方法几何算法的求解方法有很多,下面介绍几种常见的方法:1.枚举法:对于一些简单的几何问题,可以采用枚举法求解。
例如,在计算多边形的面积时,可以枚举多边形的所有顶点,计算每个顶点对应的三角形面积,最后将所有三角形面积相加得到多边形的面积。
2.扫描线法:扫描线法是一种基于二维坐标系的几何算法。
它通过扫描线逐行扫描多边形,计算多边形与扫描线的交点,从而得到多边形的边界。
扫描线法可以高效地计算多边形的面积和周长。
3.空间分割法:空间分割法是一种基于空间数据的几何算法。
它通过将空间数据分成若干个区域,然后计算各个区域之间的交集,从而得到所需的几何信息。
空间分割法可以高效地处理复杂几何体。
四、几何算法的优缺点分析几何算法的优点:1.高效性:几何算法通常具有较高的计算效率,可以快速求解几何问题。
2.通用性:几何算法可以应用于多种几何问题,具有较强的通用性。
几何算法的缺点:1.复杂性:对于一些复杂的几何问题,几何算法的求解过程可能较为复杂,难以理解和实现。
三角形算法引言三角形是几何学中的基本图形之一,具有广泛的应用。
在计算机图形学、游戏开发、物理模拟等领域,三角形算法被广泛使用。
本文将介绍常用的三角形算法及其原理,包括点的位置关系判断、边的相交检测、面的剔除等内容。
三角形的表示方法在计算机中,我们通常使用三个顶点的坐标来表示一个三角形。
以二维坐标系为例,假设一个三角形的三个顶点分别为A(x1, y1), B(x2, y2)和C(x3, y3),可以用以下方法表示:三角形ABC:A = (x1, y1)B = (x2, y2)C = (x3, y3)在三维空间中,我们可以使用类似的方式表示三角形的三个顶点的坐标。
点的位置关系判断判断一个点在三角形内部、外部还是边上是很常见的问题。
常用的方法有以下几种:1. 点在三角形内部判断方法一个点P(x, y)在三角形ABC内部的条件是:点P在三个边AB、BC和CA的同一侧。
假设三角形ABC按顺时针方向排列,点P在三边的右侧,则点P在三角形内部。
2. 点在三角形外部判断方法一个点P(x, y)在三角形ABC外部的条件是:点P在三个边AB、BC和CA的两侧。
假设三角形ABC按顺时针方向排列,点P在三边的同一侧,则点P在三角形外部。
3. 点在三角形边上判断方法一个点P(x, y)在三角形ABC边上的条件是:点P在三边AB、BC或CA上。
边的相交检测在计算机图形学中,判断两条边是否相交是一个常见的问题。
常用的方法有以下几种:1. 检测两条线段是否相交给定两条线段AB和CD,我们可以通过计算两条线段的参数方程,即求解线段AB和线段CD的交点,来判断两条线段是否相交。
2. 检测线段与直线的相交给定一条线段AB和一条直线CD,我们可以通过计算线段AB和直线CD的交点,来判断线段和直线是否相交。
3. 检测多边形边的相交给定一个多边形,我们可以通过遍历多边形的所有边,判断每一条边是否与其他边相交,来判断多边形的边是否相交。
面的剔除在计算机图形学中,三角形的面剔除是一种优化技术,用于减少不可见的三角形的绘制次数,从而提高渲染性能。
计算机图形学1. 简介计算机图形学是研究如何使用计算机来生成、处理和显示图像的一门学科。
它主要涉及图像的几何和物理特性的建模,以及图像的渲染和表示。
计算机图形学在各个领域中都有广泛的应用,包括游戏开发、电影制作、虚拟现实、医学成像等。
2. 图形学的基本概念图形学的基本概念包括点、线、多边形和曲线等基本元素,以及相应的数学方法和算法。
这些方法和算法用于描述和处理图像的几何特性,包括位置、方向、大小和形状等。
2.1 点和线在计算机图形学中,点是图像中最基本的元素,可以通过坐标系来表示。
线是由两个点之间的连接所形成的,可以通过直线方程或参数方程来描述。
2.2 多边形和曲线多边形是由多个线段连接而成的封闭图形,可以通过顶点的集合来描述。
曲线是由多个点按照一定规律连接而成的,可以通过控制点和插值方法来表示。
3. 图形的几何建模图形的几何建模是计算机图形学中的一个重要研究方向,它涉及如何使用数学模型来表示和描述物体的几何特性。
常用的几何建模方法包括点、线、面、体和曲面等。
3.1 点云和网格模型点云模型是一组离散的点的集合,它可以用于表示不规则形状的物体。
网格模型是一组由三角形或四边形面片组成的表面模型,它可以用于表示规则形状的物体。
3.2 曲面建模曲面建模是基于数学曲面的建模方法,它将物体表面抽象为由曲线和曲面组成的,可以通过控制点和插值方法来表示。
常用的曲面建模方法包括贝塞尔曲线和贝塞尔曲面等。
4. 图形的渲染和表示图形的渲染和表示是计算机图形学中的另一个重要研究方向,它涉及如何将图像的几何信息转化为可视的图像。
常用的渲染和表示方法包括光栅化、光线追踪和纹理映射等。
4.1 光栅化光栅化是将几何对象转化为像素的过程,它涉及将线段或多边形映射到屏幕上的像素点,并进行相应的着色和填充。
常用的光栅化算法包括Bresenham算法和扫描线算法等。
4.2 光线追踪光线追踪是一种以物理光线为基础的渲染方法,它从观察者的视角出发,沿着光线的路径跟踪物体的相交和反射,最终得到图像。
几何计数初步鼠标法1. 引言1.1 什么是几何计数初步鼠标法几何计数初步鼠标法是一种应用于几何计数问题中的解题方法。
它结合了几何计数和鼠标法的特点,让我们能够更快、更准确地解决各种几何计数问题。
几何计数是数学中的一个重要分支,主要研究几何图形中不同元素的组合及其数量。
而鼠标法是一种简便快捷的解题方法,通过直观的图形表示和操作,可以帮助我们更好地理解和解决问题。
几何计数初步鼠标法是一种非常实用的解题方法,可以帮助我们更好地理解和解决各种几何计数问题。
通过学习和掌握这种方法,我们能够提高解题效率,增强数学计数能力,为更复杂的几何计数问题的解决打下良好的基础。
2. 正文2.1 几何计数初步鼠标法的原理几何计数初步鼠标法是一种在几何计数问题中常用的解题方法,通过逐步分析问题、利用几何原理和技巧,最终得出正确答案的计数方法。
其原理主要包括以下几个方面:几何计数初步鼠标法要求具备一定的几何知识和计数技巧。
在解题过程中,需要根据问题的特点和要求,灵活运用几何知识进行推理和计算。
利用平行线、相似三角形、圆的性质等几何概念,解决一些计数问题。
几何计数初步鼠标法强调问题的分类和归纳。
在解决问题时,需要首先确定问题的类型,分析问题的特点和难点,然后采用相应的方法和技巧进行解题。
通过分类归纳的方式,可以更好地理解和解决各类几何计数问题。
几何计数初步鼠标法注重解题过程的逻辑性和系统性。
在利用鼠标法解题时,需要按照一定的步骤和顺序进行,确保解题过程清晰、有序、不遗漏。
也要重视解答的正确性,及时检查和验证所得结果,确保问题得到准确解决。
几何计数初步鼠标法是一种结合几何知识和计数技巧的解题方法,通过系统地分析问题、合理地运用方法、准确地检验解答,最终能够有效地解决各类几何计数问题。
它不仅有助于提高解题效率和准确率,还可以培养学生的逻辑思维和数学能力,具有重要的应用和教育价值。
2.2 步骤一:确定问题类型几何计数初步鼠标法是一种在几何计数领域中常用的解题方法。
计算几何入门及应用计算几何是计算机科学的一个重要分支,它结合了几何学与计算,研究如何使用计算方法解决几何问题。
随着计算机技术的发展,计算几何所涉及的问题越来越多,应用也变得愈加广泛。
本文将对计算几何的基本概念、应用以及相关算法进行详细讨论。
什么是计算几何计算几何是研究几何对象及其关系,使用算法和数据结构来解决几何问题的领域。
其主要研究内容包括点、线、面、体及其组合的性质和运算,如距离、夹角、面积、交点等。
它在处理具有空间特征的问题时显得尤为重要,例如计算机图形学、机器人导航、地理信息系统(GIS)、CAD(计算机辅助设计)等领域。
基本概念几何对象:在计算几何中,最基本的几何对象包括点、线段、多边形、多面体等。
空间维度:计算几何可分为一维(线)、二维(平面)和三维(空间)。
不同维度的几何问题解决方法有所不同。
组合几何:研究有限点集之间的组合关系,例如点与点之间的连线构成的图形。
算法复杂性:在解决几何问题时,算法的时间复杂性与空间复杂性是一个重要考量因素。
常用的数据结构包括平衡树、链表、栈等。
计算几何中的基本算法在计算几何中,有许多经典算法可以用来解决各种问题。
以下是一些重要的算法:凸包算法凸包是指一个点集的最小凸形状。
在二维平面上,凸包可以想象成一个橡皮筋套在点集周围。
常用的计算凸包的算法有:Graham扫描算法:先选择一个基准点,然后根据极角对其他点进行排序,最后通过规则判断哪些点构成凸包。
Jarvis行走法:从一个极点开始,不断找到下一个最远的点,直到回到起始点。
最近点对给定一组点,寻找其中距离最近的一对点。
常见的方法有:暴力搜索法:逐一比较每对点,时间复杂度为O(n^2)。
分治法:通过划分空间减少比较次数,时间复杂度降至O(n log n)。
线段相交判断两条线段是否相交是一个基本问题,可用于图形碰撞检测。
常用方法包括:扫动线法:以一条假想的垂直线从左到右移动,并利用事件队列存储可能相交的线段。
二分法程序实现平面区域计算几何计算几何是一门研究不同形状的几何图形之间的关系和属性的学科。
而平面区域计算几何则是研究平面上的区域和图形之间的关系和属性的领域。
在平面区域计算几何中,二分法是一种常见且有效的算法,能够在相当快的时间内对平面上的区域和图形进行分析和计算。
下面将介绍如何使用编程语言实现二分法程序,在计算几何问题中应用。
一、二分法算法二分法是一种基于分治思想的高效算法,其核心思想是通过将一个问题拆分为多个子问题,逐步缩小问题规模,最终得到问题的解。
在平面区域计算几何中,二分法通常被用来确定一个区域中特定位置的坐标或特定图形的性质。
下面是二分法的伪代码:```// 求解特定区域中位置的坐标或图形的性质low = 区域左下角坐标high = 区域右上角坐标while low < high:mid = (low + high) / 2if 满足条件1:high = midelse:low = mid + 1// 返回满足条件的坐标或性质return low```在二分法算法中,我们需要定义满足条件1的规则,以便在分治过程中快速定位目标区域。
对于不同问题,这个规则有很大的差异。
二、应用二分法算法解决平面区域计算几何问题使用二分法实现平面区域计算几何,需要先定义问题,然后才能确定条件1和算法规则。
这里我们的例子是一个简单的问题:给定一个二维平面上的矩形区域和一个内部点P,求该点到矩形的距离。
这个问题在计算机图形学和计算几何中是一个经典问题,可以应用于线段和多边形的求解。
二分法的核心是分治,所以我们首先要将问题分解为多个子问题,然后使用递归算法来解决它。
在这个问题中,我们可以使用水平线和垂直线将矩形划分成9个小矩形(包括本身)。
然后对每个小矩形重复这个过程,直到我们找到包含点P的最小矩形。
这个过程可以看做是一个模板,我们可以在这个过程中填充我们自己定义的条件1和算法规则。
代码实现如下:```// 定义一个二维点类class Point {double x;double y;}// 定义一个矩形类class Rect {Point topLeft;Point bottomRight;}// 定义一个函数来计算点到矩形的距离double distanceFromPointToRect(Point p, Rect rect) {// 判断点是否在矩形内if (p.x >= rect.topLeft.x && p.x <= rect.bottomRight.x &&p.y >= rect.topLeft.y && p.y <= rect.bottomRight.y) {return 0;}// 判断点在矩形的上下左右哪个区域double dx = 0.0, dy = 0.0;if (p.x < rect.topLeft.x) {dx = p.x - rect.topLeft.x;} else if (p.x > rect.bottomRight.x) {dx = p.x - rect.bottomRight.x;}if (p.y < rect.topLeft.y) {dy = p.y - rect.topLeft.y;} else if (p.y > rect.bottomRight.y) {dy = p.y - rect.bottomRight.y;}// 如果点在矩形的左上角、右上角、右下角或者左下角,直接返回距离if (dx == 0.0 || dy == 0.0) {return sqrt(dx*dx + dy*dy);}// 查找包含点P的最小子矩形Rect subRect = null;while (true) {// 将当前矩形平分为4个子矩形double midX = (rect.topLeft.x + rect.bottomRight.x) / 2.0;double midY = (rect.topLeft.y + rect.bottomRight.y) / 2.0;Rect[] subRects = {new Rect(rect.topLeft, new Point(midX, midY)),new Rect(new Point(midX, rect.topLeft.y), newPoint(rect.bottomRight.x, midY)),new Rect(new Point(midX, midY), rect.bottomRight),new Rect(new Point(rect.topLeft.x, midY), new Point(midX, rect.bottomRight.y))};// 判断点所在的子矩形if (p.x < midX) {if (p.y < midY) {subRect = subRects[0];} else {subRect = subRects[1];}} else {if (p.y < midY) {subRect = subRects[3];} else {subRect = subRects[2];}}// 如果包含点,则递归实现求解if (p.x >= subRect.topLeft.x && p.x <= subRect.bottomRight.x &&p.y >= subRect.topLeft.y && p.y <= subRect.bottomRight.y) {return distanceFromPointToRect(p, subRect);}// 否则将包含点的子矩形作为下一个矩形继续递归分治rect = subRect;}}```这个算法基于二分法思想,分治过程中计算出点P到矩形最小矩形的距离,最终得出点P到矩形的距离。
三点共线算法三点共线算法是数学中的一个重要概念,用来判断给定的三个点是否在同一条直线上。
这个算法在几何学、计算机图形学以及计算机视觉等领域中都有广泛应用。
本文将介绍三点共线算法的原理和应用,以及一些相关的概念和定理。
一、三点共线算法的原理三点共线算法的原理其实很简单,就是利用向量的线性相关性来判断三个点是否在同一条直线上。
具体来说,我们可以将三个点分别表示为向量A、B和C,然后计算向量AB和向量AC的叉积。
如果叉积为零,即(AB × AC) = 0,那么这三个点就在同一条直线上;如果叉积不为零,那么这三个点就不在同一条直线上。
三点共线算法在几何学中有广泛的应用。
例如,在解析几何中,我们经常需要判断一个三角形的三个顶点是否共线,这时就可以利用三点共线算法来判断。
此外,在计算机图形学和计算机视觉中,三点共线算法也常用于图像处理和目标识别等任务中。
三、相关概念和定理除了三点共线算法,还有一些相关的概念和定理也与之密切相关。
例如,共线点定理指出,如果一个点在一条直线上,那么它的任意两个点也在同一条直线上。
这个定理可以作为三点共线算法的基础。
还有一些定理可以用于判断三个点是否共线。
例如,如果三角形的两边的中点和第三边的一个顶点共线,那么这三个点就共线。
另外,如果一个三角形的内心和外心与三个顶点共线,那么这三个点也共线。
四、三点共线算法的优化虽然三点共线算法很简单,但是在实际应用中可能会遇到一些性能问题。
例如,当处理大规模数据时,如果对所有的三个点都执行一次三点共线算法,那么算法的时间复杂度将会很高。
为了提高算法的效率,可以采用一些优化措施,例如使用空间分割树结构来加速算法的执行。
五、总结三点共线算法是一种判断给定的三个点是否在同一条直线上的算法。
它的原理很简单,只需要计算两个向量的叉积即可。
这个算法在几何学、计算机图形学和计算机视觉等领域中有广泛的应用。
此外,还有一些相关的概念和定理可以用于判断三个点是否共线。
计算几何算法概览一、引言计算机的出现使得很多原本十分繁琐的工作得以大幅度简化,但是也有一些在人们直观看来很容易的问题却需要拿出一套并不简单的通用解决方案,比如几何问题。
作为计算机科学的一个分支,计算几何主要研究解决几何问题的算法。
在现代工程和数学领域,计算几何在图形学、机器人技术、超大规模集成电路设计和统计等诸多领域有着十分重要的应用。
在本文中,我们将对计算几何常用的基本算法做一个全面的介绍,希望对您了解并应用计算几何的知识解决问题起到帮助。
二、目录本文整理的计算几何基本概念和常用算法包括如下内容:矢量的概念矢量加减法AcGeVector2d/AcGeVector3d + - += -=等运算符重载或者setToSum矢量叉积AcGeVetor3d crossProduct折线段的拐向判断由矢量叉积的性质推出判断点是否在线段上isOn判断两线段是否相交AcgeLineSeg2d intersectWith判断线段和直线是否相交AcgeLine2d AcgeLineSeg2d intersectWith判断矩形是否包含点判断线段、折线、多边形是否在矩形中判断矩形是否在矩形中判断圆是否在矩形中判断点是否在多边形中判断线段是否在多边形内判断折线是否在多边形内判断多边形是否在多边形内判断矩形是否在多边形内判断圆是否在多边形内判断点是否在圆内判断线段、折线、矩形、多边形是否在圆内判断圆是否在圆内计算点到线段的最近点line.closestPointTo(point);计算点到折线、矩形、多边形的最近点计算点到圆的最近距离及交点坐标计算两条共线的线段的交点计算线段或直线与线段的交点求线段或直线与折线、矩形、多边形的交点求线段或直线与圆的交点凸包的概念凸包的求法三、算法介绍矢量的概念:如果一条线段的端点是有次序之分的,我们把这种线段成为有向线段(directed segment)。
如果有向线段p1p2的起点p1在坐标原点,我们可以把它称为矢量(vector)p2。
计算几何中的寻找凸壳算法在计算几何中,几何形体的寻找是一个很重要的问题。
凸壳,也称凸包,是在点集中连接所有点中的外壳形状。
寻找凸壳是计算几何中一个非常经典和重要的问题。
凸壳不仅可以应用于计算机图形学领域,还可以应用于生物学、土木工程、航空航天等领域。
在本文中,我们将介绍两种不同的计算几何中的寻找凸壳算法。
寻找凸壳的常用算法最常用但也最简单的方法是先找到一个最上方的点和一个最下方的点,然后用这两个点连接整个点集,同时将其它点分成两组。
通过实现一个 O(n^2) 的算法,我们可以寻找到点集中的最高点和最低点。
接下来,我们可以通过寻找与这条线交叉的点,将剩余的点分成两组,从而构建出凸壳形状的一条边。
在以后的操作中,我们不需要考虑被淘汰的点。
我们可以接着在两组点的内部分别进行上述过程,直到所有点都被处理完毕。
这里的时间复杂度取决于每次操作中包含的点的数量,因为每访问一个点需要推迟一个点。
因此,时间复杂度大概是 O(n^2*log n)。
该算法最早由Jarvis 算法提出,通常称为Jarvis 显式凸包算法。
算法的实现非常简单,但是效率极低。
尽管 Jarvis 算法的时间复杂度比较高,但事实证明,对于小规模的数据集, Jarvis 算法是最优的选择。
改进算法的介绍Jarvis 算法尽管容易验明,但效率很低,因此人们提出了其他更好的算法。
其中一个著名的算法是 Graham 扫描算法。
Graham扫描算法是一种基于排序思路的凸包算法,其思路是寻找最低的点,然后按极角对所有点进行排序,从而找到凸包中最右边的点。
最初,只有三个点属于凸包,然后扫描其余点。
如果要添加新点,则先使用栈保存先前的点以构建链。
该算法其核心是一个排序算法,时间复杂度高达 O(n*log n)。
但是经过改进,该算法的复杂度已经减少到了 O(n log n)。
与显式算法不同, Graham 算法使用堆栈简化空间。
总结在本文中,我们介绍了计算几何中两种不同的寻找凸壳算法:显式凸包算法和改进算法。
算法系列之九:计算几何与图形学有关的几种常用算法(一)分类:算法系列2011-12-18 23:13 8182人阅读评论(41) 收藏举报我的专业是计算机辅助设计(CAD),算是一半机械一半软件,《计算机图形学》是必修课,也是我最喜欢的课程。
热衷于用代码摆平一切的我几乎将这本教科书上的每种算法都实现了一遍,这种重复劳动虽然意义不大,但是收获很多,特别是丢弃了多年的数学又重新回到了脑袋中,算是最大的收获吧。
尽管已经毕业多年了,但是每次回顾这些算法的代码,都觉得内心十分澎湃,如果换成现在的我,恐怕再也不会有动力去做这些事情了。
在学习《计算机图形学》之前,总觉得很多东西高深莫测,但实际掌握了之后,却发现其中了无神秘可言,就如同被原始人像神一样崇拜的火却被现代人叼在嘴上玩弄一样的感觉。
图形学的基础之一就是计算几何,但是没有理论数学那么高深莫测,它很有实践性,有时候甚至可以简单到匪夷所思。
计算几何是随着计算机和CAD的应用而诞生的一门新兴学科,在国外被称为“计算机辅助几何设计(Computer Aided Geometric Design,CAGD)”。
“算法系列”接下来的几篇文章就会介绍一些图形学中常见的计算几何算法(顺便晒晒我的旧代码),都是一些图形学中的基础算法,需要一些图形学的知识和数学知识,但是都不难。
不信?那就来看看到底有多难。
本文是第一篇,主要是一些图形学常用的计算几何方法,涉及到向量、点线关系以及点与多边形关系求解等数学知识,还有一些平面几何的基本原理。
事先声明一下,文中涉及的算法实现都是着眼于解释原理以及揭示算法实质的目的,在算法效率和可读性二者的考量上,更注重可读性,有时候为了提高可读性会刻意采取“效率不高”的代码形式,实际工程中使用的代码肯定更紧凑更高效,但是算法原理都是一样的,请读者们对此有正确的认识。
一、判断点是否在矩形内计算机图形学和数学到底有什么关系?我们先来看几个例子,增加一些感性认识。
首先是判断一个点是否在矩形内的算法,这是一个很简单的算法,但是却非常重要。
比如你在一个按钮上点击鼠标,系统如何知道你要触发这个按钮对应的事件而不是另一个按钮?对了,就是一个点是否在矩形内的判断处理。
Windows 的API提供了PtInRect()函数,实现方法其实就是判断点的x坐标和y坐标是否同时落在矩形的x坐标范围和y坐标范围内,算法实现也很简单:150bool IsPointInRect(const Rect& rc,const Point& p)151{152double xr =(p.x - rc.p1.x)*(p.x - rc.p2.x);153double yr =(p.y - rc.p1.y)*(p.y - rc.p2.y);154155return((xr <=0.0)&&(yr <=0.0));156}看看IsPointInRect()函数的实现是否和你想象的不一样?有时候硬件实现乘法有困难或受限制于CPU乘法指令的效率,可以考虑用下面的函数替换,代码繁琐了一点,但是避免了乘法运算:120bool IsPointInRect(const Rect& rc,const Point& p)121{122double xl,xr,yt,yb;123124if(rc.p1.x < rc.p2.x)125{126 xl = rc.p1.x;127 xr = rc.p2.x;128}129else130{131 xl = rc.p2.x;132 xr = rc.p1.x;133}134135if(rc.p1.y < rc.p2.y)136{137 yt = rc.p2.y;138 yb = rc.p1.y;139}140else141{142 yt = rc.p1.y;143 yb = rc.p2.y;144}145146return((p.x >= xl && p.x <= xr)&&(p.y >= yb && p.y <= yt));147}由于IsPointInRect()函数并不假设矩形的两个定点是按照坐标轴升序排列的,所以算法实现时就考虑了所有可能的坐标范围。
IsPointInRect()函数使用的是平面直角坐标系,如果不特别说明,本文所有的算法都是基于平面直角坐标系设计的。
另外,IsPointInRect()函数没有指定特别的浮点数精度范围,默认是系统浮点数的最大精度,只在某些必须要与0比较的情况下,采用10-8次方精度,如无特别说明,本文的所有算法都这样处理。
一、判断点是否在圆内现在考虑复杂一点,如果图形界面的按钮不是矩形而是圆形的怎么办呢?当然就是判断点是否在圆内部。
判断算法的原理就是计算点到圆心的距离d,然后与圆半径r进行比较,若d < r则说明点在圆内,若d = r则说明点在圆上,若d > r则说明点在圆外。
这就要提到计算平面上两点距离的算法。
以下图为例,计算平面上任意两点之间的距离主要依据著名的勾股定理:图1 平面两点距离计算示意图113//计算欧氏几何空间内平面两点的距离114double PointDistance(const Point& p1,const Point& p2)115{116return std::sqrt((p1.x-p2.x)*(p1.x-p2.x)117+(p1.y-p2.y)*(p1.y-p2.y));118}一、判断点是否在多边形内现在再考虑复杂一点的,如果按钮是个不规则的多边形区域怎么办?别以为这个考虑没有意义,很多多媒体软件和游戏,通常都是用各种形状的不规则图案作为热点(Hot Spot),Windows也提供了PtInRegion() API,用于判断点是否在一个不规则区域中。
我们对问题做一个简化,就判断一个点是否在多边形内?判断点P是否在多边形内是计算几何中一个非常基本的算法,最常用的方法是射线法。
以P点为端点,向左方做射线L,然后沿着L从无穷远处开始向P 点移动,当遇到多边形的某一条边时,记为与多边形的第一个交点,表示进入多边形内部,继续移动,当遇到另一个交点时,表示离开多边形内部。
由此可知,当L与多边形的交点个数是偶数时,表示P点在多边形外,当L与多边形交点个数是奇数时,表示P点在多边形内部。
由此可见,要实现判断点是否在多边形内的算法,需要知道直线段求交算法,而求交算法又涉及到矢量的一些基本概念,因此在实现这个算法之前,先讲一下矢量的基本概念以及线段求交算法。
3.1 矢量的基础知识什么是矢量?简单地讲,就是既有大小又有方向的量,数学中又常被称为向量。
矢量有几何表示、代数表示和坐标表示等多种表现形式,本文讨论的是几何表示。
如果一条线段的端点是有次序之分的,我们把这种线段成为有向线段(Directed Segment),比如线段P1P2,如果起始端点P1就是坐标原点(0, 0),P2的坐标是(x, y),则线段P1P2的二维矢量坐标表示就是P=(x, y)。
3.2 矢量的加法和减法现在来看几个与矢量有关的重要概念,首先是矢量的加减法。
假设有二维矢量P = ( x1, y1 ),Q = ( x2 , y2 ),则矢量加法定义为:P + Q = ( x1 + x2 , y1 + y2 )同样的,矢量减法定义为:P - Q = ( x1 - x2 , y1 - y2 )根据矢量加减法的定义,矢量的加减法满足以下性质:P + Q = Q + PP - Q = - ( Q - P )图2 演示了矢量加法和减法的几何意义,由于几何中直线段的两个点不可能刚好在原点,因此线段P1P2的矢量其实就是OP2 -OP1的结果,如图2 (b)所示:3.3 矢量的叉积(外积)另一个比较重要的概念是矢量的叉积(外积)。
计算矢量的叉积是判断直线和线段、线段和线段以及线段和点的位置关系的核心算法。
假设有二维矢量P = ( x1, y1 ),Q = ( x2 , y2 ),则矢量的叉积定义为:P × Q = x1*y2 - x2*y1向量叉积的几何意义可以描述为由坐标原点(0,0)、P、Q和P + Q所组成的平行四边形的面积,而且是个带符号的面积,由此可知,矢量的叉积具有以下性质:P × Q = - ( Q × P )叉积的结果P × Q是P和Q所在平面的法矢量,它的方向是垂直与P和Q所在的平面,并且按照P、Q和P × Q的次序构成右手系,所以叉积的另一个非常重要性质是可以通过它的符号可以判断两矢量相互之间位置关系是顺时针还是逆时针关系,具体说明如下:1) 如果P × Q > 0 , 则Q在P的逆时针方向;2) 如果P × Q < 0 , 则Q在P的顺时针方向;3) 如果P × Q = 0 , 则Q与P共线(但可能方向是反的);3.4 矢量的点积(内积)最后要介绍的概念是矢量的点积(内积)。
假设有二维矢量P = ( x1, y1 ),Q = ( x2 , y2 ),则矢量的点积定义为:P·Q = x1*x2 + y1*y2向量点积的结果是一个标量,它的代数表示是:P·Q = |P| |Q| cos(P, Q)(P, Q) 表示向量P和Q的夹角,如果P和Q不共线,则根据上式可以得到向量点积的一个非常重要的性质,具体说明如下:1) 如果P · Q > 0 , 则P和Q的夹角是钝角(大于90度);2) 如果P · Q < 0 , 则P和Q的夹角是锐角(小于90度);3) 如果P · Q = 0 , 则P和Q的夹角是90度;了解了矢量的概念以及矢量的各种运算的几何意义和代数意义后,就可以开始解决各种计算几何的简单问题了,回想本文开始提到的点与多边形的关系问题,首先要解决的就是判断点和直线段的位置关系问题。
3.5 用矢量的叉积判断点和直线的关系根据矢量叉积的几何意义,如果线段所表示的矢量和点的矢量的叉积是0,就说明点在线段所在的直线上,相对于坐标原点O来说,线段的矢量其实就是线段终点P2=[x2, y2]的矢量OP2减线段起点P1=[x1, y1]的矢量OP1的结果,因此线段P1P2的矢量可以表示为P1P2=(x2 – x1, y2 – y1)。
如果要判断点P是否在线段P1P2上,就要判断矢量P1P2和矢量OP的叉积是否是0。
需要注意的是,叉积为0只能说明点P与线段P1P2所在的直线共线,并不能说明点P一定会落在P1P2区间上,因此只是一个必要条件。