Vatti clipping 算法介绍
文章目錄
- 一、背景
- 二、基本概念
- 1. 點(Vertex)
- 2. 點的順序(Vertex order)
- 3. 邊 (Edge)
- 3.1 左側邊和右側邊(Left-hand Edge and Right-hand Edge)
- 3.2 左側界和右側界 (Left Bounds and Right Bounds)
- 4. 局部最小多邊形(Local mininum)
- 5. 局部最小多邊形集(Local Mininum List: LML)
- 6. 掃描線(Scan Line)
- 7. 活躍邊(Active edge)
- 1. 對Active edge進行排序
- 三、算法介紹
- 1. 生成圖形的LML
- 2. 初始化SBL
- 3. 生成Scan Line
- 4. 找到Active Edges
- 5. 處理active edges
一、背景
Vatti clipping 算法是很多幾何圖形庫的底層實現原理, 比如clipper2就是基于Vatti clipping算法來實現的,本文介紹Vatti clipping算法中的基本概念以及其算法原理。
二、基本概念
下面是Vatti clipping算法中的基本概念:
1. 點(Vertex)
由于double在計算機中表示的精度問題,一般的幾何圖形庫支持的基本數據類型都是整型數值類型(clipper2中雖然帶有支持double類型的接口,其實現也是接收用戶輸入的double類型,轉為integer類型后再進行計算,計算完成后,轉為double類型返回給用戶),點的數據結構為:
struct Vertex {int64_t x;int64_t y; };2. 點的順序(Vertex order)
Vatti 算法中通常優先按照y值進行對點排序,如果y值相等,則按照x值進行排序,點的比較算法為:
bool operator<(const Vertex& a, const Vertex& b) {if (a.y == b.y) {return a.x < b.x;}return a.y < b.y; }3. 邊 (Edge)
一條邊e由兩個點組成: start和end,邊的起點和終點滿足: e.start < e.end,邊的數據結構為:
struct Edge {Vertex start;Vertex end; };3.1 左側邊和右側邊(Left-hand Edge and Right-hand Edge)
左和右是相對于圖形的內側區域而言的,在圖形內側的左邊的邊稱為左側邊,在圖形內側的右邊的邊稱為右側邊。如下圖1
圖1中:
- Left edges:p0p8,p8p7,p7p6p_0p_8, p_8p_7, p_7p_6p0?p8?,p8?p7?,p7?p6?, 和 p4p3,p3p2p_4p_3, p_3p_2p4?p3?,p3?p2?
- Right edges:p0p1,p1p2p_0p_1, p_1p_2p0?p1?,p1?p2?, 和 p4p5,p5p6p_4p_5, p_5p_6p4?p5?,p5?p6?
3.2 左側界和右側界 (Left Bounds and Right Bounds)
連續的左側邊組成一個左側界,連續的右側邊組成一個右側界。上圖1中:
- Left Bounds:
- B1=(p0p8,p8p7,p7p6)B_1 = (p_0p_8, p_8p_7, p_7p_6)B1?=(p0?p8?,p8?p7?,p7?p6?)
- B2=(p4p3,p3p2)B_2 = (p_4p_3, p_3p_2)B2?=(p4?p3?,p3?p2?)
- Right Bounds:
- B3=(p0p1,p1p2)B_3 =(p_0p_1, p_1p_2)B3?=(p0?p1?,p1?p2?)
- B4=(p4p5,p5p6)B_4 = (p_4p_5, p_5p_6)B4?=(p4?p5?,p5?p6?)
4. 局部最小多邊形(Local mininum)
一個局部最小多邊形(Local minimum)由一個根節點(root vertex),以及其相連的左側界和右側界組成,這些左側界和右側界同時必須滿足以下條件:
- 左側界和右側界的第一條邊不能是水平的
- 左側界和右側界的最后一條邊不能是水平的
如下圖2所示,黑色部分是根節點,綠色部分是左側界,紅色部分為右側界,下面的多邊形可以由三個黃色虛線框標出的Local mininum組成。
5. 局部最小多邊形集(Local Mininum List: LML)
將圖2中的三個黃色虛線框標出的最小多邊形放到一個集合中,并按黑色根節點的y坐標按照從小到大排序,就得到了Local mininum的集合,即LML。
6. 掃描線(Scan Line)
從下往上,經過多邊形的每一個頂點以及多邊形邊的交點的水平直線,稱為掃描線。
對于LM,如果它的根節點位于Scan Line上,那么,該LM起始于該Scan Line。
7. 活躍邊(Active edge)
如果某條非水平的邊和Scan Line相交(包含邊的起點,終點在Scan Line上,或者邊的中間部分和Scan Line相交),那么稱這條邊為活躍邊(Active edge)。根據交點在Active edge上的不同位置:
如下圖3,紅色的Active edge位于Scan Line之上,藍色的Active edge位于Scan Line之下,黑色的Active edge位于Scan Line之下或之上:
圖3:Active edge和Scan Line的關系1. 對Active edge進行排序
如果Active edge位于Scan Line之上(包含相交),這些Active edges將按照交點(與Scan Line 相交)或起點(位于Scan Line之上)的X坐標值進行排序,如果坐標值相等,將按順時針方向對這些Active edge進行排序,如下圖4,位于Scan Line之上或相交的紅色Active edges的排序如標號所示:
如果Active edge位于Scan Line之下(包含相交),這些Active edges將按照交點(與Scan Line 相交)或終點(位于Scan Line之上)的X坐標值進行排序,如果坐標值相等,將按逆時針方向對這些Active edge進行排序,如下圖5,位于Scan Line之下或相交的綠色Active edges的排序如標號所示:
三、算法介紹
Vatti clipping的核心算法分為以下幾步:
下面詳細介紹各步:
1. 生成圖形的LML
LML是根據vertex排好序了的,排序規則是根據root vertex按照點的排序規則進行排序。對于root vertex重合的情況,順序可以是任意的。
2. 初始化SBL
SBL里面是按從小到大排好序的LML的所有root vertex的Y坐標值
3. 生成Scan Line
取出并刪除SBL中的最小值,形成一條Scan Line
4. 找到Active Edges
找到和當前Scan Line相交的所有活躍邊:
那些和上一條Scan Line相交的邊或者起點和上一條Scan Line重合的邊,是位于當前Scan Line之下的邊。如下圖6所示:
- 和上一條Scan Line相交的邊或者起點和上一條Scan Line重合且終點不和當前Scan Line重合的邊,是位于當前Scan Line之上的Active Edges,如下圖7所示:
- 和上一條Scan Line相交的邊或者起點和上一條Scan Line重合且終點和當前Scan Line重合的邊,以及起點位于當前Scan Line的邊,是位于當前Scan Line之上的Active Edges,如下圖8所示:
- 對與LM,如果其root verter和當前Scan Line重合,那么它的第一條左側邊(Left edge)和第一條右側邊(Right edge),是位于當前Scan Line之上的Active Edges,如下圖9所示:
這里對于水平邊(Horizontal edges)和共線邊(Collinear edges)的處理要注意:
- Active Edges中是沒有水平邊的,對于這些和Scan Line重合的水平邊,放在一個閉區間的集合中。和Active Edges分開存放
- 對于共線的Active Edges, 這在Vatti clipping算法是必須要通過其它辦法修正的:
- 如果對于Scan line上方的兩條active edge是colinear的,那么比較長的那條邊將會被分成兩部分:和其它active edge重合的部分將會被移除,剩下的部分和圖形的其它部分向連接。
- 如果兩條colinear的active edge完全重合,那么,其中一條將會被移除,之前和被移除的active edge相連接的邊和剩下沒有被移除的active edge相連接。
對于共線的Active Edges的處理示意圖如下圖10所示:
5. 處理active edges
對于每條Active edge, 記x為下面的任意一種情況的X坐標的值:
- 如果Active edge和Scan Line相交,交點的X坐標的值
- 如果Active edge的起點和Scan Line重合,起點的X坐標的值
- 如果Active edge的終點和Scan Line重合,終點的X坐標的值
這樣,每條active edge都對應于一個x值,對于還未處理的active edges集合,則由一個x值的集合,找到最小的x值。對于下圖10中:
上圖中標紅的點是最小的x值對應的點,Scan Line上方的active edges是紅色的,Scan Line下方的active edges是藍色的,水平邊是黑色的。
對和紅點相連的active edges的進行如下處理(如適用才處理):
接下來,對沒有處理的active edges, 重復上面的步驟直到所有的active edges都處理完畢。
上面的處理過程中,有兩種特殊情況需要進行特殊處理:
這里圖15和圖16分別對應的是Scan Line位于要處理的圖形的最底部和最頂部的情況。
未完待續
Reference:
總結
以上是生活随笔為你收集整理的Vatti clipping 算法介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MATLAB函数downsample的用
- 下一篇: 微信公众号经验