110,534
社区成员
发帖
与我相关
我的任务
分享
public enum PolygonDirection
{
/// <summary>
/// 无方向性,不构成简单多边形
/// </summary>
NON = 0x0000,
/// <summary>
/// 正向简单多边形(逆时针)
/// </summary>
Forward = 0x0001,
/// <summary>
/// 负向简单多边形(顺时针)
/// </summary>
Negative = 0x0010
}
/// <summary>
/// 判断点是否在某条直线上
/// </summary>
/// <param name="point">被判断的点</param>
/// <param name="pLineStart">直线经过的点1</param>
/// <param name="pLineEnd">直线经过的点2</param>
/// <returns></returns>
public static bool IsOnline(PointF point, PointF pLineStart, PointF pLineEnd)
{
float dx = pLineStart.X - pLineEnd.X;
float dy = pLineStart.Y - pLineEnd.Y;
if (dx == 0f)
{//垂直于X轴
if (point.X == pLineStart.X)
{
return true;
}
else
{
return false;
}
}
if (dy == 0)
{//垂直于Y轴
if (point.Y == pLineStart.Y)
{
return true;
}
else
{
return false;
}
}
float k = dy / dx;
float b = pLineStart.Y - k * pLineStart.X;
float vy = k * point.X + b;
if (point.Y == vy)
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// 两个向量的叉乘,两条向量必须是经过平移后有一个公用点
/// </summary>
/// <param name="pOne">第一个向量的起点</param>
/// <param name="pTwo">(公用点)第一个向量的终点,同时也是经过平移后的第二个向量的起点</param>
/// <param name="pThree">第二个向量的终点</param>
/// <returns>返回叉乘后的正负</returns>
private static float GetPointsMultiplicationCross(PointF pLast,PointF pCenter,PointF pNext)
{
float value = 0f;
float dx1 = pCenter.X - pLast.X;
float dx2 = pNext.X - pCenter.X;
float dy1 = pNext.Y - pCenter.Y;
float dy2 = pCenter.Y - pLast.Y;
value = dx1 * dy1 - dx2 * dy2;
return value;
}
/// <summary>
/// 获取点列表中的极值点(凸顶点)
/// </summary>
/// <param name="lst">点列表</param>
/// <returns></returns>
private static List<KeyValuePair<int, PointF>> GetExtremalPoints(List<PointF> lst)
{
List<KeyValuePair<int, PointF>> extremalPoints = new List<KeyValuePair<int, PointF>>();
KeyValuePair<int, PointF> minxPoint = new KeyValuePair<int, PointF>();//最左X极值点
KeyValuePair<int, PointF> minYPoint = new KeyValuePair<int, PointF>();//最上Y极值点
KeyValuePair<int, PointF> maxxPoint = new KeyValuePair<int, PointF>();//最右X极值点
KeyValuePair<int, PointF> maxyPoint = new KeyValuePair<int, PointF>();//最下Y极值点
float minx = float.MaxValue;
float miny = float.MaxValue;
float maxx = float.MinValue;
float maxy = float.MinValue;
for (int i = 0; i < lst.Count; i++)
{
if (lst[i].X < minx)
{//求最左极值点
minx = lst[i].X;
minxPoint = new KeyValuePair<int, PointF>(i, lst[i]);
}
if (lst[i].Y < miny)
{//求最上极值点
miny = lst[i].Y;
minYPoint = new KeyValuePair<int, PointF>(i, lst[i]);
}
if (lst[i].X > maxx)
{//求最右极值点
maxx = lst[i].Y;
maxxPoint = new KeyValuePair<int, PointF>(i, lst[i]);
}
if (lst[i].Y > maxy)
{//求最下极值点
maxy = lst[i].Y;
maxyPoint = new KeyValuePair<int, PointF>(i, lst[i]);
}
}
extremalPoints.Add(minxPoint);
extremalPoints.Add(minYPoint);
extremalPoints.Add(maxxPoint);
extremalPoints.Add(maxyPoint);
for (int i = 0; i < extremalPoints.Count; i++)
{//移除重复点
for (int j = extremalPoints.Count - 1; j > i; j--)
{
if (extremalPoints[i].Key == extremalPoints[j].Key)
{
extremalPoints.RemoveAt(j);
}
}
}
return extremalPoints;
}
/// <summary>
/// 根据构成简单多边形的点的序列,判断多边形的方向性
/// </summary>
/// <param name="lst">简单多边形包含的点的序列</param>
/// <returns>返回多边形的方向性</returns>
public static PolygonDirection GetPolyGonDirection(List<PointF> lst)
{
if (lst.Count < 3)
{
return PolygonDirection.NON;
}
#region []
//else if (lst.Count == 3)
//{
// if (IsOnline(lst[1], lst[0], lst[2]))
// {//三点共线
// return PolygonDirection.NON;
// }
// else
// {
// }
//}
#endregion []
else
{
PointF p1 = lst[0];
PointF p2 = lst[lst.Count - 1];
bool collineation = true;
for (int i = 1; i < lst.Count - 1; i++)
{
if (!IsOnline(lst[i], p1, p2))
{
collineation = false;
break;
}
}
if (collineation)
{//共线
return PolygonDirection.NON;
}
//极值点列表int:点在原始点列表中的索引,PointF:点的坐标
List<KeyValuePair<int, PointF>> protrudPolyLst = MathUtil.GetExtremalPoints(lst);
if (protrudPolyLst.Count > 0)
{
int index = protrudPolyLst[0].Key;
PointF centerPoint = protrudPolyLst[0].Value;
PointF lastPoint = PointF.Empty;
PointF nextPoint = PointF.Empty;
if (index == 0)
{
lastPoint = lst[lst.Count - 1];
nextPoint = lst[index + 1];
}
else if (index == lst.Count - 1)
{
lastPoint = lst[index - 1];
nextPoint = lst[0];
}
else
{
lastPoint = lst[index - 1];
nextPoint = lst[index + 1];
}
float value = MathUtil.GetPointsMultiplicationCross(lastPoint, centerPoint, nextPoint);
if (value < 0)
{
return PolygonDirection.Forward;
}
else if (value > 0)
{
return PolygonDirection.Negative;
}
else
{
return PolygonDirection.NON;
}
}
else
{//没有极值点
return PolygonDirection.NON;
}
}
}