骨架提取
基于 Voronoi 图的 简单多边形骨架提取

计算几何课程设计报告基于Voronoi图的简单多边形骨架提取引言骨架(Skeleton)又称中轴(Medial Axis),通常使用烧草模型和最大球(圆)模型来描述。
骨架有着与原物体相同的拓扑和形状信息,是一种性能优良的几何特征,能够有效的描述物体,因此,在物体识别、路径规划、医学工程等领域多有应用。
在物体识别等应用领域里,骨架提取的输入可以看作是空间内的点构成的多边形,对于多边形的骨架提取也成为了这些应用的基本技术,具有重要的应用意义。
在此次课程设计中,我们实现了基于Voronoi 图的任意多边形的骨架提取,并提供了多边形骨架提取的演示界面。
多边形骨架一个多边形的骨架,如上图所示,可以看作是由无数点对之间的骨架点组成的。
两点间的骨架(skeleton)(等同于对中轴(medial axis)的求取)是到两点距离相等的点的轨迹,它是两点连线的垂直平分线,每一点所邻接的半平面是到其距离最小的点集相应地可扩展为离散点集的中轴定义。
它是下列性质点的轨迹:其上任一点到最近两离散点距离相等,相应地也产生各点到其距离最小的点集;两线间的中轴是到两线距离相等的点的轨迹,它在两线相交时为角平分线——两线平行时为到两线距离——的平行线,每一线所邻接并以中轴为界的区域是到其距离最小的点集。
一线和一点间的中轴是到该点(线距离相等的点的轨迹,它是以该点为焦点、该线为准线的抛物线。
该点或线所邻接并以中轴为界的区域是到其距离最小的点集。
多边形骨架的几何算法多边形骨架(中轴)的几何算法,是由多边形的某一点开始,找出参与中轴线计算的相应的线段与线段、点与线段、点与点,实质都转化为求某个特定点(中轴转折点)的问题,因此也就是找点对序列的方法,基本的多边形骨架抽取的数据组织和算法梗概如下:从数据结构的组织上讲:实际多边形的中轴是一个多层次的环、树结构,且层次是不能限制的。
尽管一个多边形总是确定的、有限的,但复杂的多边形结构的复杂程度很难事先洞察,其各层次都可以生长,结构不定,数据组织困难,算法也困难。
骨架提取与重建

形态学骨架提取与重建摘要:本文首先介绍了三种骨架抽取算法, 并选取了最大圆盘的形态学骨架抽取算法作为研究对象,在c++编程的实验基础上,展示了基于形态学的图像骨架提取和图像重建的过程。
关键词:数学形态学;骨架提取;骨架重建骨架是图象几何形态的一种重要拓扑描述。
利用骨架表示原始图像,可以在保持图象重要拓扑特征的前提下, 减少图象中的冗余信息。
因此, 被广泛应用于生物形状描述, 模式识别, 工业检测, 定量金相以及图象压缩编码等领域。
1 骨架抽取的几种模型随着研究的深入, 人们提出了多种骨架化算法, 下面首先讨论一下三种最常用的算法。
1.1 中轴变换法: 中轴可以用下面的例子来形象的说明, 设想t = 0 时刻, 将目标边界各处同时点燃, 火的前沿以匀速向目标蔓延, 当前沿相交时火焰熄灭, 火焰熄灭点的集合就构成了中轴。
通常我们对目标图像的细化处理, 就是将图像上的文字、曲线、直线等几何元素的线条沿着中心轴线将其细化成一个象素宽的线条的处理过程。
1.2 影响区骨架法: 首先介绍一下测地距离和测地影响区的概念。
测地距离(),d x y以x , y为端点, 包含在A 中的最短距离。
在A图1 中xy为欧氏距离, ,xA Ay为测地距离。
图1 测地距离 图2 最大圆盘方式定义的中轴测地影响区()A i IZ B :设B 为A 中一个集合, 它由多个连通子集组成, 记为12,,k B B B 。
连通成分i B 的测地影响区()A i IZ B , 由A 中距i B 的测地距离比距B 的其他连通成分距离都要小的所有点集组成。
()[]{()}:,,,,A i A i IZ B p A j i k j i d P B =∈∀∈≠ (1)其中, k 为B 中连通成分的个数。
由此得到影响区骨架( SK I Z ) 的定义。
影响区骨架( S K I Z ) :在A 中不属于任何一个B 的测地影响区的点集, 构成影响区骨架, 用()A SKIZ B 表示:()()1k A A i i SKIZ B A Y IZ B ==- (2) 1.3 基于最大圆盘的形态学骨架抽取算法B l um 与N ag l e 等人对区域的骨架作了很形象的描述。
骨架提取算法的研究及在异形纤维中的应用

中图分 类号 : P314 T 9.1
文献标 志码 : A
A u y o elt n De er ia in a d St d fSk e o t m n to n
t e Ap l a i n i o i d Fi er h p i t n Pr fl b s c o e
Ab ta t sr c :Th ee mi ain o r f e ie ’ k lt ni ni o t n r -r c si gm eh df rp o i d ed tr n to fp o i df r Ss eeo a l b s mp ra tp ep o e sn t o o r fl e f e ’ d n iyn e a s h u b ro r n h si e e s r o b ac ltd A k lt n d tr n to i r Sie t ig b c u et en m e fb a c e n c s a yt ec lua e . s eeo ee mi ain b f S ag rt m sp o o e ,i hc h ii u c v rs t a eo tie isl h o g h ac lt n O lo ih wa r p s d nw ih t em nm m o e e nb b an d f ty t r u h t ec lu ai f c r o t e c rea e ti t h o a e ta on e a d t e e g n o ain. a d t e h p i h o r ltd ma rx wi t e lc lc n r l p it s t n h d e i fr t h m o n h n t e u hl l
p u i g t es al rn h Th ie ’ o oo y if r t n i wel r s r e n t eag rt m ,wh c a r nn h m l b a c . efb r St p lg o ma i l p e e v d i h lo ih n o s ih h s
c++ 代码 从骨架线提取端点和拐点

在这篇文章中,我们将深入讨论如何从C++代码中提取骨架线的端点和拐点。
骨架线是指在图像或者图形中具有一定宽度的线条的中心线,提取骨架线的端点和拐点对于图像处理和模式识别中的很多应用都非常重要。
在C++中,我们可以利用一些图像处理的库来实现这一目标,例如OpenCV等。
我们需要了解骨架线的特点和提取端点和拐点的意义。
骨架线的端点是指骨架线上的端点,而拐点则是指骨架线上的拐角处。
提取这些点的目的在于分析骨架线的形状,以便进行更深入的图像分析和识别。
接下来,让我们来分析如何从C++代码中实现端点和拐点的提取。
我们可以通过图像处理库中的相关函数来实现这一目标。
我们需要对图像进行预处理,包括灰度化、二值化和边缘检测等操作。
我们可以利用骨架线提取算法来获取骨架线,并进一步提取端点和拐点。
在C++代码中,我们可以使用OpenCV库来实现骨架线的提取和端点/拐点的获取。
我们可以利用OpenCV中的函数来进行图像的预处理,包括cvtColor()进行灰度化、threshold()进行二值化、Canny()进行边缘检测等。
我们可以利用OpenCV中的findContours()函数来提取骨架线,再利用一些自定义的算法来获取端点和拐点。
在实现端点和拐点的提取过程中,我们需要考虑一些特殊情况,例如端点和拐点的定义、算法的复杂度和效率等。
我们还需要考虑如何对提取出的端点和拐点进行进一步的处理和利用,例如在图像识别、模式匹配、形状分析等领域中的具体应用。
总结来说,从C++代码中提取骨架线的端点和拐点是一个复杂而有价值的任务。
我们可以通过图像处理库中的相关函数来实现这一目标,例如利用OpenCV来进行图像的预处理和骨架线的提取,然后利用一些自定义的算法来获取端点和拐点。
这一过程涉及到图像处理、算法设计和应用等多个领域,对于我们深入理解图像结构和形状分析具有重要意义。
希望本文可以帮助您更深入地理解这一主题,同时也能够对您在C++代码中的实际应用有所帮助。
三角网格模型骨架提取算法

随着计算机图形学的发展,对三维模型的研究日益深入,骨架作为形状表示的一种有效形式,在三维模型的各个研究领域被运用。
骨架的狭义定义最初由Blum [1]提出,当时他称骨架为“中轴”(Medial Axis )[2]。
骨架的经典定义有两种[3]:一种是烧草模型,如图1所示,从模型表面开始点火,火焰从物体边界上的两点同时向内部推进,轨迹随时间形成等距的同心圆,同心圆的相遇点所构成的集合即为骨架;另外一种是更直观的定义,即最大圆盘模型。
如图2所示,骨架点是所有最大圆盘的圆心集合,最大圆盘即是完全包含在物体内部且至少与物体边界相切于两点的圆。
骨架上的每一个点都是这些内切圆的圆心,这些圆沿着骨架分布正好填充物体的内部。
由于模型的骨架很好地保留了模型的拓扑形收稿日期:2019-05-14作者简介:王洪申(1969—),男,甘肃兰州人,博士,教授,研究方向:CAD/CAM 。
†通讯联系人,E-mail :*****************三角网格模型骨架提取算法王洪申,张家振†,张小鹏(兰州理工大学机电工程学院,甘肃兰州730000)摘要:骨架图能够直观表达三维模型几何形状,很好地反映模型的拓扑特征,在工业机器人抓取、特征识别等领域有着广泛的应用。
针对三角网格表达的工业零件给出一种骨架提取算法,该算法采用Reeb 图对三角网格进行骨架的抽取运算。
首先读取三角网格文件,并对复杂的三角网格进行简化处理,然后遍历所有的三角网格,采用Dijkstra 算法抽取基本点集,根据定义的连续函数计算每个顶点的函数值,最后根据函数值得出模型的基本骨架。
实验表明,该算法具有良好的计算效果和效率,提取出的骨架图较好地保存了三维模型拓扑结构和姿态,可作为后续研究三维模型搜索的特征描述符。
关键词:骨架图;三角网格;三维模型;拓扑结构;Reeb 图中图分类号:G633.6文献标识码:ATriangular Mesh Model Skeleton Extraction AlgorithmWANG Hong-shen ,ZHANG Jia-zhen †,ZHANG Xiao-peng(School of Mechanical and Electrical Engineering ,Lanzhou University of Technology ,Lanzhou ,Gansu 730000,China )Abstract :The skeleton diagram can visually express the geometry of the 3D model and reflect the topological features of themodel well.It has a wide range of applications in the fields of industrial robot capture and feature recognition.A skeleton extraction al -gorithm is proposed for the industrial parts expressed by the triangle mesh.The algorithm uses the Reeb diagram to extract the skeleton from the triangular mesh.First read the triangle mesh file ,and simplify the complex triangle mesh ,then traverse all the triangle mesh -es ,extract the basic point set by Dijkstra algorithm ,calculate the function value of each vertex according to the defined continuous function ,and finally The function deserves the basic skeleton of the model.Experiments show that the proposed algorithm has goodcomputational efficiency and efficiency.The extracted skeleton map preserves the topology and pose of the 3D model ,and can be usedas a feature descriptor for the subsequent research of 3D model search.Key words :skeleton diagram ;triangular mesh ;3D model ;topology ;Reeb diagram第39卷第2期2020年6月计算技术与自动化Computing Technology and AutomationVol.39,No.2Jun.2020文章编号:1003—6199(2020)02—0145—05DOI :10.16339/ki.jsjsyzdh.202002029态及其连接特性,所以经常被用于模型渲染、模型表面重建、碰撞检测、模型检索等应用中,在工业零件的视觉识别领域也有广泛的用途。
l1中值算法提取骨架代码 -回复

l1中值算法提取骨架代码-回复中值算法提取骨架代码,是一种图像处理算法,旨在通过处理图像中的二值化图像,从而获得对象的“骨架”。
骨架是指在不改变对象的拓扑结构和几何形状的前提下,将对象形态减少到最简化的表示形式。
1. 了解中值算法提取骨架的基本概念和原理:中值算法是一种迭代算法,将二值化图像中所有非零像素点的邻域中的像素值的中值作为该像素点的新值。
通过不断迭代,直到新生成的像素值不再发生改变,即达到稳定状态。
该算法可以实现图像的平滑化,去除噪声,并提取图像的骨架。
2. 了解算法实现的步骤:a. 读入并预处理图像:将图像转为灰度图,并进行二值化处理,得到二值化的图像。
b. 初始化:为输出骨架图像创建一个与原始图像相同大小的新图像,并将其初始化为全零。
c. 迭代过程:i. 对二值化的图像进行腐蚀操作,将所有像素点的邻域值设为最小值。
ii. 对腐蚀后的图像进行膨胀操作,将所有像素点的邻域值设为最大值。
iii. 将腐蚀后的图像与膨胀后的图像进行减法操作,得到新的骨架图像。
iv. 判断新的骨架图像是否与上一次迭代生成的骨架图像相同,如果相同则停止迭代,否则继续迭代。
d. 输出结果:输出最终的骨架图像。
3. 实现中值算法提取骨架的代码:import cv2import numpy as npdef median_skeleton_extraction(image):# 转为灰度图gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 二值化处理_, binary_image = cv2.threshold(gray_image, 127, 255,cv2.THRESH_BINARY)# 初始化骨架图像skeleton_image = np.zeros_like(binary_image, dtype=np.uint8)# 迭代过程while True:# 腐蚀操作eroded_image = cv2.erode(binary_image, np.ones((3, 3), np.uint8), iterations=1)# 膨胀操作dilated_image = cv2.dilate(eroded_image, np.ones((3, 3), np.uint8), iterations=1)# 骨架图像skeleton_image = cv2.subtract(binary_image,dilated_image, dtype=np.uint8)# 判断是否终止迭代if np.array_equal(skeleton_image, binary_image):breakbinary_image = skeleton_image.copy()return skeleton_image# 读取图像image = cv2.imread("input_image.png")# 提取骨架skeleton = median_skeleton_extraction(image)# 显示结果cv2.imshow("Skeleton", skeleton)cv2.waitKey(0)cv2.destroyAllWindows()以上是中值算法提取骨架的代码实现,通过调用OpenCV库中的相关函数来实现中值算法的迭代过程。
枝干骨架提取关键算法的研究

枝干骨架提取关键算法的研究摘要骨架反映了物体的拓扑信息,因而是描述物体和压缩数据的有力工具,在图形学和图像处理中,骨架也很好地保持了网格模型和图像中物体的“骨干”信息,得到了较好的骨架就可以重构物体或模型的原有形态。
本文针对传统的骨架提取算法虽然可以获得物体的中轴,但是存在计算复杂,提取的骨架有很多多余分支或者骨架断裂等缺点,提出了基于高斯混合模型和交互式图像分割技术的用户手绘的草图来辅助识别骨架提取算法。
关键词骨架提取;高斯混合模型;交互式图像分割0 引言骨架提取作为识别物体的一种方法,最初只针对于二维图像,后来也应用于三维模型,但两者的目的是相通的:将二维轮廓或三维面片浓缩为若干曲线的集合,即骨架。
图像物体骨架提取的方法通常分为基于对称轴分析的骨架提取算法、细化算法和形状分解算法。
1 高斯混合模型高斯混合模型(Gaussian Mixture Model)是若干个高斯分布的线性组合,因为单个高斯分布所具有的性质在实际应用中无法完美地与数据契合,但是多个高斯分布通过一定的线性组合的系数组合在一起就可以很好地描述任何分布的实际数据。
高斯混合模型采用高斯概率密度函数精确地量化事物,将一个事物分解为若干的基于高斯概率密度函数(正态分布曲线)形成的模型,学术界认为任何一个概率分布都可以由多个正态分布或高斯分布逼近和近似。
同时高斯混合模型是若干个单一高斯分布的加权组合,模型中每个高斯分布占据一定的权重并且分别表示数据集在某一方面的聚集分布特征,因而整个高斯混合模型就描述了数据集在全局上的特征分布情况。
2骨架的识别2.1枝干骨架的定义骨架是描述物体主要拓扑结构的有力工具,同样,对于树木来说,枝干结构反映了树木的基本拓扑信息和几何形态,所以枝干骨架很好地表示了枝干分支结构的拓扑以及几何信息。
孙若曦等人利用图像分割、距离变换和最大值抑制的综合方法尽管得到了枝干的中轴,但是其方法需要将图像转化为二值图像,且基于细化的骨架提取会造成骨架断开,失去连通性,这不利于我们寻找枝干的父子关系。
三维模型骨架提取算法研究与实现

背景
随着三维模型处理技术的不断发展,三维模型骨架提取算法的研究也取得了 一定的进展。然而,现有的算法存在一些问题和挑战,如计算量大、实时性差、 对复杂结构处理能力不足等。因此,研究更为高效和可靠的三维模型骨架提取算 法显得尤为重要。
提取算法
本次演示提出了一种基于距离变换的三维模型骨架提取算法。该算法首先对 三维模型进行距离变换,得到每个点的最小距离值,并确定这些值对应的特征点。 然后,通过这些特征点,运用分形维数法计算出骨架的形状和结构。
实验设计与结果
为了验证本次演示提出的方法,我们进行了大量实验。首先,我们收集了一 个包含多种三维CAD模型的数据集,并将其划分为训练集和测试集。然后,我们 训练了卷积神经网络模型,用于提取三维CAD模型的形状特征。
ห้องสมุดไป่ตู้
在特征提取阶段,我们比较了不同的卷积神经网络架构,如VGG、ResNet和 U-Net,以选择最佳的网络结构。同时,我们还研究了不同的表面分割策略对特 征提取效果的影响。在特征检索阶段,我们采用余弦相似度算法对特征向量进行 匹配,并比较了不同图割算法对检索准确率的影响。
2、实验流程及数据处理方法
实验中采用了本次演示提出的基于距离变换的三维模型骨架提取算法,对各 个数据集进行骨架提取。在实验过程中,针对不同类型的数据集,根据其特点和 难点,适当地调整了算法参数,以获得最佳的性能表现。
3、实验结果及分析
通过对比和分析实验结果,我们发现本次演示提出的算法在处理多种类型的 数据集时,均能获得较好的性能表现。在计算效率和准确率方面,该算法也具有 一定的优势。实验结果证明了该算法的有效性和可靠性。
三维模型骨架提取算法研究与 实现
01 引言
03 提取算法 05 结论与展望
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
平面简单多边形的直骨架实现定义2D简单多边形的直骨架(straight skeleton),它是一种新的多边形的骨架,是仅由简单多边形的一些边的角平分线所组成的(如图1所示)。
轮廓边(contour edge),原简单多边形上的边。
图1中红色的边。
骨架边(skeleton edge),由原多变形的边与边的角平分线所组成的边。
图1中蓝色和绿色的边。
轮廓顶点(contour vertex),就是原多边形上的顶点。
图1中红色轮廓边相交的顶点骨架顶点(skeleton vertex),是由骨架边相交而成的顶点。
图1中绿色边和绿色边,蓝色边和蓝色边,或绿色边和蓝色边相交而成的顶点。
轮廓平分线(contour bisector),产生该种平分线的两条边在轮廓是相邻的。
图1中绿色的边。
内部平分线(inner bisector),产生该种平分线的两天边在轮廓上不是相邻的。
图1中蓝色的边。
图1 简单多边形及其直骨架实验内容本次作业的主要内容是实现2D简单多边形(包括凸多边形,非凸多边形,带洞多边形)的直骨架生成算法,以及在骨架生成之后,提供了骨架等高线的生成过程演示和简单多边形的三维屋顶演示效果。
实验目的2D简单多边形的直骨架有着广泛的应用,它相对于其它一般的骨架更加具有实际的应用价值,因此实验该种骨架的生成还是十分具有学习意义的。
实验步骤AICHHOLZER在[1]中提出了一种2D简单多边形直骨架的概念,在该论文中他给多边形直骨架的概念给了一个明确、清晰地定义:从每一条多边形的轮廓边上向多边形内部穿过一个三维的平面,所有的这些平面与多边形的夹角都是相等的(我们演示的时候是设为45°),这些平面在三维空间上相交,相交所产生的三维的包围多面体上的边就相当于是多边形的屋顶的棱(可以认为原简单多边形是你家房子的墙壁,然后所生成直骨架就相当于你家的屋顶),然后包围多面体上的所有边和顶点在原简单多边形上进行投影,投影所得到的点和边就是简单多边形的骨架边和骨架顶点,也就是我们实验要最终求得的点和边。
数据结构设计多向链表:由于轮廓顶点与骨架顶点之间的拓扑关系十分复杂,一个轮廓顶点不但要指向原多变形上prev和next轮廓顶点,还要指向其相关的骨架上的顶点,这就要求我们设计使用多向链表来维护整个多边形及其骨架的拓扑关系。
见图2。
actNext ,指向该顶点的在多向链表中的下一个未处理的顶点(active vertex)。
prev ,指向轮廓上的一条边的起点,该边是参与该顶点的所发出的平分线计算的逆时针方向的第一条边。
actPrev ,指向该顶点的在多向链表中的上一个未处理的顶点(active vertex)。
next,指向轮廓上的一条边的起点,该边是参与该顶点的所发出的平分线计算的逆时针方向的第二条边。
startProcessed ,指向该顶点(作为一条边的始点)所产生事件顶点(skeleton vertex2)。
endProcessed ,指向该顶点(作为一条边的终点)所产生事件顶点(skeleton vertex2)。
Active 顶点,未曾发生事件的顶点。
processed 顶点,已经被处理的顶点。
图2 多向链表在发生edge 事件的前后变化优先队列:由于整个直骨架的构造算法是基于扫描线算法,因此优先队列这种数据结构是主要用来在O(lgn)的时间内插入新的事件点,在O(1)的时间内取出下一个事件点。
在我们的算法实现的过程中,由于针对于每一个事件点都只有两种操作插入和取出,不存在在算法执行的过程中某个事件点的键值发生改变的情况,因此用STL 中提供的priority_queue 就可以满足需求了。
算法介绍简单多边形的判定我们实现的这个直骨架生成算法不仅能针对凸多边形,而且能针对非凸多边形,甚至可以针对带洞的多边形。
简单多边形的一个很重要的判定原则本可以用Chazelle 提出的算法来在O(n)的时间内解决,但是为了方便用户在输入多边形的点的时候一旦发生了非多边形的输入可以及时改正,我们就采用了用户每输入一个新的顶点就判断一次是否是简单多边形,每次判定都在O(n)时间内完成。
带洞的简单多边形,这个洞必须要完全位于多边形外轮廓的内部,而且存在多个洞的情况,洞与洞之间不能重叠,更重要的是不能存在洞中有洞的情况。
洞位于外轮廓的内部的判定首先判定当前输入的洞上顶点是否位于外轮廓的内部,我们使用的是射线法,从当前输入的顶点向某一个方向发射一条无穷长的射线,如果该与该射线相交的顶点数为奇数,则认为该顶点位于多边形外轮廓的内部,而且还要判定该洞顶点所产生的内轮廓边是否和其他边相交,如果不相交则说明该内轮廓边位于外轮廓的内部,等到一个洞画完,而且每个洞上的顶点都能通过以上判定,则可以断定该洞位于外轮廓的内部,否则一旦发现某个顶点不符合要求,就取消该顶点,提示用户重新输入。
洞与洞之间是否重叠或是洞中有洞的判定由于我们对用户每次输入的顶点都进行的是否存在边相交的情况,因此洞与洞相交的情况也就判定了。
但是有可能存在洞中有洞(一个洞完全包含在另一个洞里)的情况(见图3),我们采用了也是射线法,在目前绘制的这个洞结束时,在每个其它的每个洞中,任意的挑一个顶点来进行射线法测试,如果当前绘制的洞完全包含其它洞,则射线相交的次数为偶数次(目前绘制的洞完全包含在其它洞中的情况,在每个顶点判定是否位于外轮廓的内部就可以判定了,因为这种情况射线相交的次数也同样为偶数次)。
图3 洞1完全包含洞2角平方线(bisector)的计算传统意义上的角平分线就是相邻两条边的夹角平分线,在我们的算法执行的过程中,需要计算各种类型的角平分线,而且不仅是针对相邻的两条边,不相邻的两条边同样也可以进行计算角平分线,图4列出了5情况下角平分线的计算。
图4 两条轮廓边的角平分线计算(情况(1)两条边是相邻非平行,且顶点是凸点;情况(2)的两条边是相邻非平行,但顶点是凹点;情况(3)的两条边是相邻且平行;情况(4)的两条边非相邻且平行;情况(5)的两条边是非相邻且非平行)。
扫描线算法初始化初始化工作主要是计算每个顶点的角平分线,以及算出该角平分线与相邻两个角的角平分线的交点哪个离对应的边更近,选取距离较近的交点(图5中的点V1)压入优先队列中,这是凸点的情况(图5中的点A)。
如果是凹点的话(图5中的点B),还要计算该点可能发生split事件的分裂点到对应的边的垂直距离,选择距离最短的分裂点(图5中的点V2)压入到栈中。
计算这个距离的过程略微复杂,详细过程在后面会进行描述。
图5 V1和V2为被放入优先队列的交点(其它A点对应的交点未在该图中画出)此外,初始化的工作还包括将轮廓上的顶点按顺序通过指针prev,next,actPrev,actNext 相邻,在初始化的时候prev和actPrev同样指向逆时针方向的上一个顶点,next和actNext 同样指向逆时针方向的下一个顶点。
在计算骨架的过程中,actNext和actPrev指针会指示出当前活动的顶点,而next和prev指针会指示出与当前点相关的轮廓上的点的位置,原本就在轮廓上的点的next和prev指针从初始化之后一直保持不变。
具体算法(步骤)如下:A. 将轮廓的顶点数据按顺序存放在一条多向链表中,并给指针prev,next,actPrev,actNext赋值,使得这些顶点正确相连,如果多边形内部有洞的话,每一个洞上的顶点都存为一条链表,最后将所有链的头指针保存在一个头指针列表中;B.对所有的顶点(也包括洞上的顶点)计算角平分线;C.建立一个“距离”越小优先级越高的“交点”优先队列Q ,对所有的顶点,若该点为凸点,则计算它所对应的角平分线与相邻的两个顶点的角平分线的交点,选取到对应边的垂直距离较小的顶点放入Q中,如图5中粉色的线条所示,我们称这种顶点对应的事件为edge事件;若该点为凹点,则除了要进行上述操作以外,还要针对可能发生的split事件进行分裂点的计算,如图5中绿色的线条所示,从B点沿两侧的边的反方向发出两条射线,对所有的轮廓上的边进行相交测试,对于满足如下条件的边:1) 与两条射线均相交;2) 方向正确,例如在图5中,B点的对边AA的方向必须是从右至左的。
分别计算两条射线与它们中的每一条边围成的三角形的角平分线的交点,此时需要进一步的判断,判断计算出的交点是否在对边的两个顶点对应的角平分线包围的区域里,即图5中的判断V2是否在灰色区域里,若不在,则排除该点,若在,则该点为一个候选点。
得到所有的候选点之后,选出其中到达对边的垂直距离最小的点,放入Q中。
计算骨架计算骨架这部分主要的流程是每次从优先队列Q中pop出一个顶点,然后对其进行处理,将产生出的骨架的边记录下来,并更新相关顶点在多向链表中的连接关系。
具体算法(步骤)如下:重复以下步骤直至队列Q为空:A. 从Q中pop出一个顶点V,如果该顶点为edge事件产生的交点且产生该交点所对应的两个顶点至少有一个已经被处理过的话,那么重复步骤A;如果该顶点为split事件产生的分裂点且产生该分裂点所对应的凹点已经被处理过的话,那么重复步骤A;B. 如果V为edge事件产生的交点:1)设产生V的两个顶点为V a和V b,输出边(V, V a) 和(V, V b) 到记录骨架的边列表中,并标记V a、V b为已访问。
如果V a的actPrev的actPrev指针指向V b的话,说明V a,V b的活动链上只剩下三个顶点了,那么也将边(V, V a->actPrev)进行输出,并标记V a->actPrev为已访问;2)更新链表指针:V->next ← V b->nextV->prev ← V a->prevV->actNext ← V b->actNextV b->actNext ← VV->actPrev ← V a->actPrevV a->actPrev ← V3)对新顶点V计算角平分线,并比较它与活动链上相邻的两个顶点(即actPrev和actNext指针所指向的顶点)的平分线的交点到对应的轮廓上的边的垂直距离,将较小的放入队列Q中;C. 如果V为split事件产生的分裂点:1)设产生V的凹点B为V a,对边的起点为V b,输出边(V, V a) 到记录骨架的边列表中,并标记V a为已访问;2)由于split事件会将V a所在的活动链分成两个链,因此建立两个新顶点V1和V2,它们的位置是相同的,但是在链表中的连接关系是不同的,两个点属于不同的活动链,如图6所示。
图6 split事件处理示意图,虚线为活动链更新链表指针:图6所示是一种最简单的情况,在这种情况中V b和V b->next还尚未被处理,但是在多数时候,V b或者V b->next可能已经被处理,不在活动链上了,这时候的处理过程会比较复杂,有时候还会出现多次split的现象,关于上述这些复杂情况的处理方法,请见接下来的轮廓边被多个凹点所分裂的情况分析,在这里只描述如图6所示的最简单的情形下链表的连接关系。