多边形顶点顺时针排放

发布时间 2023-11-28 22:48:11作者: yanghui01

效果

 

//凹多边形,凸多边形都能判断
public static bool IsVertsClockwise(Vector2[] verts)
{
    if (verts.Length < 3)
        return false;

    //劣角数量比优角数量多
    //假设是顺时针, 那叉乘结果为正的次数比负多
    int positionNum = 0;
    int negativeNum = 0;
    for (int i = 0; i < verts.Length; ++i)
    {
        var a = verts[i];
        var b = verts[(i + 1) % verts.Length];
        var c = verts[(i + 2) % verts.Length];
        var ba = a - b;
        var bc = c - b;
        float cross = V2Cross(ref ba, ref bc);
        if (cross > 0)
            positionNum++;
        else
            negativeNum++;
    }
    var result = positionNum > negativeNum;
    return result;
}

//多边形顶点按顺时针排列
public static bool SortVertsClockwise(Vector2[] verts)
{
    if (!IsVertsClockwise(verts))
    {
        for (int i = 0; i < verts.Length / 2; ++i)
        {
            var temp = verts[i];
            int swapIndex = verts.Length - 1 - i;
            verts[i] = verts[swapIndex];
            verts[swapIndex] = temp;
        }
        return true;
    }
    return false;
}

 

测试代码

using System.Collections.Generic;
using UnityEngine;

public class SortVertsClockwiseTest : MonoBehaviour
{
    public Transform[] m_Verts;

    void Start()
    {
        var vertList = new List<Vector2>();
        for (int i = 0; i < m_Verts.Length; ++i)
        {
            var vert = m_Verts[i];
            if (null != vert)
            {
                vertList.Add(vert.position);
                Debug.Log($"{i}: {vert.position}");
            }
        }

        var arr = vertList.ToArray();
        if (Shape2DHelper.SortVertsClockwise(arr))
        {
            Debug.Log($"Sorted");
            for (int i = 0; i < arr.Length; ++i)
            {
                Debug.Log($"{i}: {arr[i]}");
            }
        }
    }


#if UNITY_EDITOR

    public Color m_Edge0Color = Color.red;
    public Color m_Edge1Color = Color.green;

    private void OnDrawGizmos()
    {
        if (null != m_Verts)
        {
            DrawPolyTrans(m_Verts);
        }
    }

    public void DrawPolyTrans(Transform[] verts)
    {
        Transform firstVert = null; //第1个非null顶点
        Transform lastVert = null;
        for (int i = 0; i < verts.Length; ++i)
        {
            if (i <= 1) Gizmos.color = m_Edge0Color;
            else if (2 == i) Gizmos.color = m_Edge1Color;
            else Gizmos.color = Color.white;
            
            var vert = verts[i];
            if (null == vert) continue;

            if (null == lastVert)
            {
                firstVert = vert;
                lastVert = vert;
                continue;
            }
            Gizmos.DrawLine(lastVert.position, vert.position);
            lastVert = vert;
        }
        Gizmos.color = Color.white;
        //首尾相接
        if (null != lastVert && null != firstVert)
        {
            Gizmos.DrawLine(lastVert.position, firstVert.position);
        }
    }

#endif

}

 

参考 

如何判断一个点在多边形内部(二) - 知乎 (zhihu.com)