多邊形裁剪一:Sutherland-Hodgman演算法
Sutherland-Hodgman演算法
Sutherland-Hodgman演算法也叫逐邊裁剪法,該演算法是薩瑟蘭德(I.E.Sutherland)和霍德曼(Hodgman)在1974年提出的。這種演算法採用了分割處理、逐邊裁剪的方法。
一,基本思想:
一次用視窗的一條邊裁剪多邊形。
考慮視窗的一條邊以及延長線構成的裁剪線該線把平面分成兩個部分:可見一側;不可見一側。多邊形的各條邊的兩端點S、P。它們與裁剪線的位置關係只有四種
情況(1)僅輸出1個頂點P;
情況(2)輸出0個頂點;
情況(3)輸出線段SP與裁剪線的1個交點I;
情況(4)輸出線段SP與裁剪線的1個交點I和1個終點P
1、已知:多邊形頂點陣列src,頂點個數n,
定義新多邊形頂點陣列dest。
2、賦初值:用變數flag來標識:
0表示在內側,1表示在外側。
3、對多邊形的n條邊進行處理,對當前點號的考慮為:0~n-1。
for(i=0;i<n;i++)
{
if(當前第i個頂點是否在邊界內側?)
{
if(flag!=0) /*前一個點在外側嗎?*/
{
flag=0;/*從外到內的情況,將標誌置0,作為下一次迴圈的前一點標誌*/
(dest + j) =求出交點; /*將交點dest放入新多邊形*/
j++;
}
(dest + j)= (src + i); /*將當前點srci放入新多邊形*/
j++;
}
else
{
if(flag==0) /*前一個點在內側嗎?*/
{
flag=1;/*從內到外的情況,將標誌置1,作為下一次迴圈的前一點標誌*/
(dest + j) =求出交點; /*將交點dest放入新多邊形*/
j++;
}
}
s= (src + i); /*將當前點作為下次迴圈的前一點*/
}
三,演算法特點:
Sutherland-Hodgeman多邊形裁剪演算法具有一般性,被裁剪多邊形可以是任意凸多邊形或凹多邊形,裁剪視窗不侷限於矩形,可以是任意凸多邊形。
上面的演算法是多邊形相對視窗的一條邊界進行裁剪的實現,對於視窗的每一條邊界依次呼叫該演算法程式,並將前一次裁剪的結果多邊形作為下一次裁剪時的被裁剪多邊形,即可得到完整的多邊形裁剪程式。
- //點在有向線段那側
- /*
- 向量叉積法
- 為簡單計,測試點表示為P點。假設視窗邊界方向為順時針,如圖中所示,對於其中任一邊界向量,從向量起點A向終點B看過去:
- 如果被測試點P在該邊界線右邊(即內側),AB×AP的方向與X-Y平面垂直並指向螢幕裡面,即右手座標系中Z軸的負方向。
- 反過來,如果P在該邊界線的左邊(即外側),這時AB×AP的方向與X-Y平面垂直並指向螢幕外面,即右手座標系中Z軸的正方向。
- 設:點P(x,y)、點A(xA,yA)、點B(xB,yB),
- 向量AB={(xB-xA),(yB-yA)},
- 向量AP={(x-xA),(y-yA)},
- 那麼AB×AP的方向可由下式的符號來確定:
- V=(xB-xA)·(y-yA)-(x-xA)·(yB-yA) (3-14)
- 因此,當V≤0時,P在邊界線內側;
- 而V>0時,P在邊界線外側。
- */
- static int _RtInSide(RtVector vector, RtPoint point)
- {
- return (vector.ep.x - vector.sp.x) * (point.y - vector.sp.y) - (vector.ep.y - vector.sp.y) * (point.x - vector.sp.x);
- }
- //多邊形點必須是順時針方向
- int rtPrunePSH(RtPoint* src, int num, RtPoint** dest, int* total)
- {
- int i = 0, j = 0, k = -1, flag = 0;
- RtPoint start, stop;//被剪裁多邊形
- RtPoint sp, ep;//剪裁視窗
- RtPoint* temp = NULL;
- temp = (RtPoint*)malloc(sizeof(RtPoint) * 3 * (*total));
- if (temp == NULL) return -1;
- sp = *(src + num - 1);
- for ( i = 0; i < num; i++)//剪裁視窗
- {
- ep = *(src + i);
- start = *((*dest) + *total - 1);
- flag = _RtInSide(rtVector(sp, ep), start) > 0 ? 0 : 1;
- for ( j = 0; j < *total; j++)//被剪裁的多邊形
- {
- stop = *((*dest) + j);
- if (_RtInSide(rtVector(sp, ep), stop) <= 0)//當前第i個頂點是否在邊界內側
- {
- if (flag == 0)/*前一個點在外側嗎?*/
- {
- flag = 1;/*從外到內的情況,將標誌置0,作為下一次迴圈的前一點標誌*/
- k++;
- CRtPoint<double> point;
- CRtPoint<int> st(sp.x, sp.y), et(ep.x, ep.y);
- CRtLine<int> v1(st, et);
- st.SetData(start.x, start.y);
- et.SetData(stop.x, stop.y);
- CRtLine<int> v2(st, et);
- v2.Intersect(v1,point);
- (temp + k)->x = point[0];/*將交點放入新多邊形*/
- (temp + k)->y = point[1];
- }
- k++;
- *(temp + k) = stop;/*將當前點pi放入新多邊形*/
- }
- else
- {
- if (0 != flag)/*前一個點在內側嗎?*/
- {
- flag = 0;/*從內到外的情況,將標誌置1,作為下一次迴圈的前一點標誌*/
- k++;
- CRtPoint<double> point;
- CRtPoint<int> st(sp.x, sp.y), et(ep.x, ep.y);
- CRtLine<int> v1(st, et);
- st.SetData(start.x, start.y);
- et.SetData(stop.x, stop.y);
- CRtLine<int> v2(st, et);
- v2.Intersect(v1,point);
- (temp + k)->x = point[0];/*將交點放入新多邊形*/
- (temp + k)->y = point[1];
- }
- }
- start = stop;/*將當前點作為下次迴圈的前一點*/
- }
- sp = ep;
- *total = k + 1;
- memcpy(*dest, temp, sizeof(RtPoint) * (*total));
- k = -1;
- }
- return 0;
- }
相關文章
- 多邊形裁剪二:Weiler-Atherton演算法演算法
- OpenGL 學習 06 多邊形偏移 裁剪 混合 抗鋸齒
- Python 實現任意多邊形的最大內切圓演算法_任意多邊形最大內切圓演算法Python演算法
- opencv多邊形逼近OpenCV
- SVG <polygon> 多邊形SVGGo
- 多邊形填充-活動邊表法
- 線段與多邊形關係的演算法演算法
- 求多邊形凸包(線性演算法)--陳氏凸包演算法--演算法
- [CSS LEARN]Border與多邊形CSS
- 【JAVA】多邊形重心計算Java
- Facebook 面試題 | 凸多邊形面試題
- 單一div的正多邊形變換(純CSS)CSS
- matlab繪製正多邊形Matlab
- 【計算幾何】多邊形交集
- 微信小程式-測試遊戲生成六邊多邊形微信小程式遊戲
- 雙效合一的SVG多色描邊變形動畫SVG動畫
- 折線(Polyline)、多邊形(Polygon)Go
- 判斷點是否在多邊形內斷點
- [WebGL入門]十四,繪製多邊形Web
- 視覺化學習:利用向量判斷多邊形邊界視覺化
- 判斷點是否在多邊形內部斷點
- 【計算幾何】多邊形點集排序排序
- [WebGL入門]六,頂點和多邊形Web
- iOS 繪圖 - 如何繪製一個多邊形能力分佈圖iOS繪圖
- 一個Vue媒體多段裁剪元件Vue元件
- html5利用canvas圓形和多邊形程式碼例項HTMLCanvas
- 地圖演算法(二):判斷當前點是不是在該多邊形上地圖演算法
- 計算任意多邊形的面積(Android)Android
- C 實現射線檢測多邊形碰撞
- canvas實現的多邊形程式碼例項Canvas
- 【計算幾何】點在多邊形內部
- [CareerCup] 7.2 Ants on Polygon 多邊形上的螞蟻Go
- ios Image裁剪成圓形的方法iOS
- 基於C#的多邊形衝突檢測C#
- CAD繪圖工具中的正多邊形命令繪圖
- 百度地圖繪製多邊形區域地圖
- 如何利用框選工具獲取多邊形範圍?
- android下不規則多邊形填充點陣圖Android