从相反的法线方向观察,顺时针还是逆时针是相反的。
多边形的时针方向与法线方向的关系呈右手法则关系。
GoogleEarth中的面具有时针方向,法线方向为正向,反之为负向
GoogleEarth的垂面在法线方向为亮色,反向为暗色
GoogleEarth的水平面或斜面无论法线指向天空还是地面,背离地面的一侧总是亮色。
要保证多边形的各侧向垂面的法线总是朝外(保持外侧面为亮面),若该多边形为顺时针,则各垂面边框按从高点起始,先画水平线到下点,再画垂线到低点,最后回到高点的方法。反之,若该多边形为逆时针,则各垂面边框应从高点开始,先画垂线到低点,再画水平线到下点,最后回到高点的方法。
换句话说,假设各垂面都从高点开始画,如果多边形是顺时针的,则先画水平线;如果多边形是逆时针的,则先画垂直线。归纳为 “顺高水,逆高垂”。
凸多边形只有具有一个时针方向,但凹多边形的凸边和凹边时针方向不相同。一个多边形无论凹凸,判断每相邻两边的时针方向更有意义。由3点构成的两边,计算这3点的卷积(CorssProduct),卷积为正是逆时针,卷积为负是顺时针。
卷积=(ΔXi,ΔYi)×(ΔXi+1,ΔYi+1),即 cp=(xi-xi-1)×(yi+1-yi)-(yi-yi-1)×(xi+1-xi), 若cp>0,该点为逆时针点。反之为顺时针点。
同时,如果一个多边形是凸多边形,那么,它每个顶点的卷积都为正或都为负。凹多边形的所有顶点的卷积有的为正有的为负。
此外,如果多边形存在重合的两点,或连续3点在一条直线上,那么,卷积=0,没有时针方向,也不区分凹凸。
代码示例1:判断一个多边形是顺时针还是逆时针
/*
Return the clockwise status of a curve, clockwise or counterclockwise
n vertices making up curve p
return 0 for incomputables eg: colinear points
CLOCKWISE == 1
COUNTERCLOCKWISE == -1
It is assumed that
- the polygon is closed
- the last point is not repeated.
- the polygon is simple (does not intersect itself or have holes)
*/
int ClockWise(XY *p,int n)
{
int i,j,k;
int count = 0;
double z;
if (n < 3)
return(0);
for (i=0;i<n;i++) {
j = (i + 1) % n;
k = (i + 2) % n;
z = (p[j].x - p[i].x) * (p[k].y - p[j].y);
z -= (p[j].y - p[i].y) * (p[k].x - p[j].x);
if (z < 0)
count--;
else if (z > 0)
count++;
}
if (count > 0)
return(COUNTERCLOCKWISE);
else if (count < 0)
return(CLOCKWISE);
else
return(0);
}
代码示例2:判断一个多边形是凸多边形还是凹多边形
Return whether a polygon in 2D is concave or convex
return 0 for incomputables eg: colinear points
CONVEX == 1
CONCAVE == -1
It is assumed that the polygon is simple
(does not intersect itself or have holes)
*/
int Convex(XY *p,int n)
{
int i,j,k;
int flag = 0;
double z;
if (n < 3)
return(0);
for (i=0;i<n;i++) {
j = (i + 1) % n;
k = (i + 2) % n;
z = (p[j].x - p[i].x) * (p[k].y - p[j].y);
z -= (p[j].y - p[i].y) * (p[k].x - p[j].x);
if (z < 0)
flag |= 1;
else if (z > 0)
flag |= 2;
if (flag == 3)
return(CONCAVE);
}
if (flag != 0)
return(CONVEX);
else
return(0);
}