天天看點

多邊形坐标點記錄是順時針還是逆時針的判斷

參考連結:http://hi.baidu.com/op_kaixinguo/item/e5c9ed3c9a8adb079dc65ee5

工作中遇到了之前在嘗試針對一個多邊形拆分成多個三角形以供三維顯示的問題,最後渲染不出來,發現時三角形方向相反,導緻背面畫布上去。是以從網上找了些相關資料,判斷一個多邊形描述頂點是順時針還是逆時針的方法。簡單描述如下:

極值計算法——因為多邊形中任意三個相鄰頂點所構成的順序和整體多邊形相同,是以在構成多邊形的頂點中,我們選擇最右邊(最上,最左,最下都可)的頂點P1,然後取與其相臨的兩個頂點(P2,P3),由着三個點來做判斷。

具體方法,我們參照三維中向量叉積的說明,兩個向量叉積,可以獲得其法線的方向。那麼通過簡單的坐标計算可以獲得由三個點構成的向量。

V1=P1-P2;

V2=p3-p1;

VResult = V1*V2。因為我們是在二維抽象出來的三維向量,是以V1,V2的z值都為0,是以Vresult指向的方向,機其Z值的正負便可用來做順時針,逆時針的判斷标準。

實作理論描述到此,下面給出一個AS編寫的判斷方法:參數是指定的多邊形的頂點,這裡因為多邊形在一個平面上,是以傳入三維點的z值都為0.

private function convertClockwise(points:Vector.<Vector3D>):void
		{
			//點首尾重疊,總數大于4才說明有面(說明下:小弟這裡使用的資料定義中多邊形首位是同一個點,即三角形需要四個點定義,四邊形需要5個點定義等等,,,飛這種情況的大家自己修改下就OK了)
			if(points && points.length >= 4)
			{
				//找到最大點的索引
				var maxNum:Number = Number.NEGATIVE_INFINITY;
				var maxIndex:int = -1;
				for(var i:int = 0; i < points.length; i++)
				{
					if(points[i].x > maxNum)
					{
						maxNum = points[i].x;
						maxIndex = i;
					}
				}
				
				if(maxIndex == -1)
				{
					return;
				}
				//根據最大 X 前後兩點與最大點構成的面積是正還是負來判斷點的方向
				var maxPoint:Vector3D = points[maxIndex];
				var prePoint:Vector3D;
				var nextPoint:Vector3D;
				for(var j:int = maxIndex - 1; j != maxIndex; j--)
				{
					//逆序找前一個點
					if(j == -1) j = points.length - 1;
					if(points[j].x != maxPoint.x)
					{
						prePoint = points[j];
						break;
					}
					else
					{
						maxIndex--;
						maxPoint = points[j];
					}
				}
				
				if(maxIndex == points.length - 1)
				{
					nextPoint = points[0];
				}
				else
				{
					nextPoint = points[maxIndex + 1];
				}
				
				if(null == prePoint || prePoint == nextPoint)
				{
					return;
				}
				//計算面積,叉積
				var vector1:Vector3D = prePoint.subtract(maxPoint);
				var vector2:Vector3D = maxPoint.subtract(nextPoint);
				vector1.z = 0;
				vector2.z = 0;
//				vector1.normalize();
//				vector2.normalize();
				var sub:Vector3D = vector1.crossProduct(vector2);
				if(sub.z > 0)
				{
					points.reverse();
				}
			}
		}