日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Vatti clipping 算法介绍

發布時間:2023/12/8 编程问答 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 (圖片來源:Computer graphics and geometric modeling: implementation and algorithms )

圖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組成。

圖2

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上的不同位置:

  • 如果交點是Active edge的起點,那么稱該Active edge位于Scan Line之上
  • 如果交點是Active edge的終點,那么稱該Active edge位于Scan Line之下
  • 如果交點是Active edge除掉起點和終點的其它點,那么稱該Active edge位于Scan Line之下或之上
  • 如下圖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的排序如標號所示:

    圖4:位于Scan Line之上的Active edge的排序

    如果Active edge位于Scan Line之下(包含相交),這些Active edges將按照交點(與Scan Line 相交)或終點(位于Scan Line之上)的X坐標值進行排序,如果坐標值相等,將按逆時針方向對這些Active edge進行排序,如下圖5,位于Scan Line之下或相交的綠色Active edges的排序如標號所示:

    圖5:位于Scan Line之下的Active edge的排序。 共線的Active edge可以隨意排序。

    三、算法介紹

    Vatti clipping的核心算法分為以下幾步:

  • 生成圖形的LML
  • 根據LML的root vertex,生成一個Scan Beam List(SBL), SBL里面是按從小到大排好序的root vertex的Y坐標值
  • 從SBL中取出最小的Y值,找到和縱坐標值為Y的Scan line相交的所有活躍邊(Active edges)
  • 處理找到的Active edges
  • 將每條Active edge的終點的Y坐標加入到SBL, 并將SBL維持在有序狀態
  • 找出和當前Scan line相交的邊的交點以及從SBL中獲得的Y坐標生成的下一條Scan Line相交的交點
  • 處理這些位于Scan beam內部的交點(不含Scan beam上部的交點)
  • 將Scan Line移動到Scan beam上部,找到對應的Active edges
  • 重復4-9步驟直到所有的圖形都處理到了
  • 下面詳細介紹各步:

    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之下的Active Edges
    那些和上一條Scan Line相交的邊或者起點和上一條Scan Line重合的邊,是位于當前Scan Line之下的邊。如下圖6所示:
  • 圖6
  • 找到位于Scan Line之上的Active Edges
    • 和上一條Scan Line相交的邊或者起點和上一條Scan Line重合且終點不和當前Scan Line重合的邊,是位于當前Scan Line之上的Active Edges,如下圖7所示:
    圖7
    • 和上一條Scan Line相交的邊或者起點和上一條Scan Line重合且終點和當前Scan Line重合的邊,以及起點位于當前Scan Line的邊,是位于當前Scan Line之上的Active Edges,如下圖8所示:
    圖8
    • 對與LM,如果其root verter和當前Scan Line重合,那么它的第一條左側邊(Left edge)和第一條右側邊(Right edge),是位于當前Scan Line之上的Active Edges,如下圖9所示:
    圖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所示:

    圖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中:

    圖10

    上圖中標紅的點是最小的x值對應的點,Scan Line上方的active edges是紅色的,Scan Line下方的active edges是藍色的,水平邊是黑色的。

    對和紅點相連的active edges的進行如下處理(如適用才處理):

  • 將Right-hand Edge上的vertex添加到左側的polygon, 如下圖11所示:
  • 圖11
  • 在Scan Line下方的Active edge的終點叫做top vertices,將它們添加到Scan Line下方的polygon, 如下圖12所示:
  • 圖12
  • 在Scan Line上方的Active edge的起點叫做bottom vertices,將它們添加到Scan Line上方的polygon, 如下圖13所示:
  • 圖13
  • 將Left-hand Edge上的vertex添加到右側的polygon, 如下圖14所示:
  • 圖14

    接下來,對沒有處理的active edges, 重復上面的步驟直到所有的active edges都處理完畢。
    上面的處理過程中,有兩種特殊情況需要進行特殊處理:

  • 如果Scan Line下方沒有active edges,那么左側的polygon必須拆分成兩個,如下圖15虛線所示:
  • 圖15
  • 如果Scan Line上方沒有active edges,那么左側的polygon和右側的polygon必須合并成1個,如下圖16虛線所示:
  • 圖16

    這里圖15和圖16分別對應的是Scan Line位于要處理的圖形的最底部和最頂部的情況。

    未完待續


    Reference:

  • https://github.com/dpuyda/triclipper/blob/master/docs/how_it_works.md#local-minimums
  • 總結

    以上是生活随笔為你收集整理的Vatti clipping 算法介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。