Exemple #1
0
        /// <summary>
        /// 检查所给点集是否为顺时针排序(向量叉乘的法线朝向)
        /// </summary>
        /// <returns></returns>
        public static bool CheckVector(List <Vector3> points)
        {
            // 创建一个除去自身的 多边形,判断是否为内点(凹点)
            List <Vector3> polygon = new List <Vector3>(points);

            polygon.RemoveAt(0);

            Vector3 vector3_1 = points[0] - points[1];
            Vector3 vector3_2 = points[points.Count - 1] - points[0];

            Vector3 nom = Vector3.Cross(vector3_1, vector3_2);  // 算出法线方向。Unity为左手坐标系, 使用左手定则

            //是否是凹点
            if (Math2d.IsPointInsidePolygon(points[0], polygon))
            {
                // 法线方向朝下。即逆时针排序,需要反转
                if (nom.y < 0)
                {
                    return(false);
                }
            }
            else   // 凸点
            {
                // 法线方向朝上。即逆时针排序,需要反转
                if (nom.y > 0)
                {
                    return(false);
                }
            }
            return(true);
        }
Exemple #2
0
        /// <summary>
        /// 返回三角形的内部(整数)顶点
        /// </summary>
        /// <param name="trianglePoints">三角形的三个顶点</param>
        /// <returns></returns>
        public static List <Vector3> GetPointsInTriangle(List <Vector3> trianglePoints)
        {
            // 取出所围的四边形
            float xMin = Mathf.Min(Mathf.Min(trianglePoints[0].x, trianglePoints[1].x), trianglePoints[2].x);
            float zMax = Mathf.Max(Mathf.Max(trianglePoints[0].z, trianglePoints[1].z), trianglePoints[2].z);
            float zMin = Mathf.Min(Mathf.Min(trianglePoints[0].z, trianglePoints[1].z), trianglePoints[2].z);

            List <Vector3> InsidePoints = new List <Vector3>(); // 内部点集
            Vector3        pointTmp     = Vector3.zero;         // 临时点
            List <Vector3> crossPoints  = new List <Vector3>(); // 交点点集(2个点)

            // 遍历四边形的内部所有点
            for (int z = (int)zMin, iLength = (int)zMax + 1; z < iLength; z++)
            {
                pointTmp.Set(xMin, 0, z);                                                         // 设置临时点(固定x,将z递增)
                Math2d.IsPointInsidePolygon(pointTmp, trianglePoints.ToArray(), out crossPoints); // 获取z轴平行线与三角形的交点

                // 循环添加两个交点之间的网格点
                for (int x = (int)crossPoints[0].x, length = (int)crossPoints[crossPoints.Count - 1].x + 1; x < length; x++)
                {
                    InsidePoints.Add(new Vector3(x, 0, z));
                }
            }
            return(InsidePoints);
        }
Exemple #3
0
        /// <summary>
        /// 获取两点组成的矩形边框
        /// </summary>
        /// <param name="start">起始点</param>
        /// <param name="end">终止点</param>
        /// <param name="width">宽度</param>
        /// <returns></returns>
        public static Vector2[] GetRect(Vector2 start, Vector2 end, float width)
        {
            Vector2[] rect = new Vector2[4];
            Vector2   dir  = Math2d.GetHorizontalDir(end - start);

            rect[0] = start + dir * width;
            rect[1] = start - dir * width;
            rect[2] = end + dir * width;
            rect[3] = end - dir * width;

            return(rect);
        }
Exemple #4
0
        /// <summary>
        /// 通过给定网格间隔,获取三角形内部的网格点
        /// </summary>
        /// <param name="trianglePoints">三角形顶点</param>
        /// <param name="pieceX">X的间隔</param>
        /// <param name="pieceZ">Z的间隔</param>
        /// <returns></returns>
        public static List <Vector3> GetPointsInTriangle(Vector3[] trianglePoints, float pieceX, float pieceZ)
        {
            float halfX = 0.5f * pieceX;
            float halfZ = 0.5f * pieceZ;

            // 归置三角形顶点
            for (int i = 0; i < trianglePoints.Length; i++)
            {
                trianglePoints[i].x = trianglePoints[i].x - trianglePoints[i].x % pieceX + halfX;
                trianglePoints[i].z = trianglePoints[i].z - trianglePoints[i].z % pieceZ + halfZ;
            }
            // 取出所围的四边形
            float xMin = Mathf.Min(trianglePoints[0].x, trianglePoints[1].x, trianglePoints[2].x);

            xMin = xMin - xMin % pieceX - halfX;      // 取到所在的网格中心点
            float zMax = Mathf.Max(trianglePoints[0].z, trianglePoints[1].z, trianglePoints[2].z);

            zMax = zMax + zMax % pieceZ + halfZ;
            float zMin = Mathf.Min(trianglePoints[0].z, trianglePoints[1].z, trianglePoints[2].z);

            zMin = zMin - zMin % pieceZ - halfZ;


            List <Vector3> InsidePoints = new List <Vector3>(); // 内部点集
            Vector3        pointTmp     = Vector3.zero;         // 临时点
            List <Vector3> crossPoints  = new List <Vector3>(); // 交点点集(2个点)

            // 遍历四边形的内部所有点
            for (float z = zMin; z <= zMax; z += pieceZ)
            {
                pointTmp.Set(xMin, 0, z);                                               // 设置临时点(固定x,将z递增)

                Math2d.IsPointInsidePolygon(pointTmp, trianglePoints, out crossPoints); // 获取z轴平行线与三角形的交点

                if (crossPoints.Count == 2)
                {
                    // 循环添加两个交点之间的网格中心点
                    for (float x = Mathf.Min(crossPoints[0].x, crossPoints[1].x); x <= Mathf.Max(crossPoints[0].x, crossPoints[1].x); x += pieceX)
                    {
                        InsidePoints.Add(new Vector3(x, 0, z));
                    }
                }
                crossPoints.Clear();
            }
            return(InsidePoints);
        }
Exemple #5
0
        /// <summary>
        /// 将一个多边形转化为多个三角形
        /// </summary>
        /// <param name="points"></param>
        /// <returns></returns>
        public static List <Vector2[]> PolygonToTriangles(List <Vector2> points)
        {
            if (points.Count < 3)
            {
                return(null);
            }
            List <Vector2[]> triangles = new List <Vector2[]>();
            int index = points.Count - 1;
            int next;
            int prev;

            while (points.Count > 3)
            {
                List <Vector2> polygon = new List <Vector2>(points);
                polygon.RemoveAt(index);

                //是否是凹点
                if (!Math2d.IsPointInsidePolygon(points[index], polygon.ToArray(), false))
                {
                    // 是否是可划分顶点:新的多边形没有顶点在分割的三角形内
                    if (IsFragementIndex(points, index, false))
                    {
                        //可划分,剖分三角形
                        next = (index == points.Count - 1) ? 0 : index + 1;
                        prev = (index == 0) ? points.Count - 1 : index - 1;

                        triangles.Add(new Vector2[]
                        {
                            points[index],
                            points[prev],
                            points[next]
                        });

                        points.RemoveAt(index);

                        index = (index + points.Count - 1) % points.Count;       // 防止出现index超出值域
                        continue;
                    }
                }
                index = (index + 1) % points.Count;
            }
            triangles.Add(new Vector2[] { points[1], points[0], points[2] });

            return(triangles);
        }
Exemple #6
0
        /// <summary>
        /// 获取扇形区域的点集合(包括圆心点)没有地平线以下的区域
        /// </summary>
        /// <param name="origin">圆心点</param>
        /// <param name="tarPoint"></param>
        /// <param name="alpha">x,z轴张角</param>
        /// <param name="theta">x,y轴张角</param>
        /// <returns></returns>
        public static Vector3[] GetSectorPoints_2(Vector3 origin, Vector3 tarPoint, float alpha, float theta)
        {
            List <Vector3> points = new List <Vector3>();

            int halfAlpha = (int)(alpha / 2);

            Vector3 startVector_1 = tarPoint - origin;                                     // 获取底面中间向量

            float tempHeight = Mathf.Tan(theta * Mathf.Deg2Rad) * startVector_1.magnitude; // 扇形区域最边缘高度

            // 获取扇形下表面和下表面的半径
            float radiusDown = (tarPoint - origin).magnitude;
            float radiusUp   = radiusDown / Mathf.Cos(theta * Mathf.Deg2Rad); // 获得扇形顶面半径

            // 获取扇形弧边所有点的方向向量
            List <Vector3> dirsDown = new List <Vector3>();
            List <Vector3> dirsUp   = new List <Vector3>();

            for (int i = -halfAlpha, j = 0; i <= halfAlpha; i += 3, j++)
            {
                // 获取下弧边的方向向量
                Vector2 temp = Math2d.GetTargetVector(new Vector2(startVector_1.x, startVector_1.z), i);
                dirsDown.Add(new Vector3(temp.x, 0, temp.y));

                // 获取上弧边的方向向量
                Vector3 targetDir = temp.magnitude / Mathf.Cos(i * Mathf.Deg2Rad) * dirsDown[j].normalized + Vector3.up * tempHeight;
                dirsUp.Add(targetDir);
            }

            // 获取扇形所有点
            points.Add(origin);
            for (int i = 0; i < dirsDown.Count; i++)
            {
                points.Add(dirsDown[i].normalized * radiusDown + origin);
            }
            points.Add(origin);
            for (int i = 0; i < dirsUp.Count; i++)
            {
                points.Add(dirsUp[i].normalized * radiusUp + origin);
            }

            return(points.ToArray());
        }
Exemple #7
0
        /// <summary>
        /// 以index点和前后两个点构造一个三角形,判断点集内的其余点是否全部在这个三角形外部(忽略y轴)
        /// </summary>
        public static bool IsFragementIndex(List <Vector3> verts, int index, bool containEdge = true)
        {
            int            len          = verts.Count;
            List <Vector3> triangleVert = new List <Vector3>();
            int            next         = (index == len - 1) ? 0 : index + 1;
            int            prev         = (index == 0) ? len - 1 : index - 1;

            triangleVert.Add(verts[prev]);
            triangleVert.Add(verts[index]);
            triangleVert.Add(verts[next]);
            for (int i = 0; i < len; i++)
            {
                if (i != index && i != prev && i != next)
                {
                    if (Math2d.IsPointInsidePolygon(verts[i], triangleVert.ToArray(), containEdge))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }