用数学方法解决工程问题系列(三) 判断任意给定一点是否在多边形内

来源:互联网 发布:线割编程招聘 编辑:程序博客网 时间:2024/04/25 08:15

项目里有这样一个需求,需要把一组矩形合并成一个多边形,这个多边形正好把所有矩形包在里面,而且是最小多边形。这里面尝试了好几种方案,不过每一种方案里都有这样一个步骤,判断给定的点在不在给定的矩形区域内。因为这是一个被频繁调用的方法,所以需要找出最优的实现。

  • 最先尝试的是使用内角和法,将这个在网上有详细说明和C++代码,改成C#代码如下:
            Line[] lineArray = new Line[vertexArray.Length];            for (int index = 0; index < vertexArray.Length; index++)            {                if (vertexArray[index] == point)        //判断点与顶点重合                {                    return true;                }                lineArray[index] = new Line(point, vertexArray[index]);            }            Array.Sort(lineArray);            for (int index = 0; index < lineArray.Length - 1; index++)            {                if (lineArray[index].IncludedAngleWith(lineArray[index + 1]) >= 180)                {                    return false;                }            }            if (lineArray[lineArray.Length - 1].IncludedAngleWith(lineArray[0]) >= 180)            {                return false;            }            return true;
  • 使用DotTrace监测,发现因为调用次数非常多,总的消耗的时间太多,鉴于项目里只需要判断是否在矩形内,于是改用叉积法:
            PointF[] vertexArray = beanRect.apexPoints; // 矩形的四个顶点            float cross1, cross2;            float pointX = grid.CenterPoint.X + offsetX; // 点的X坐标            float pointY = grid.CenterPoint.Y + offsetY; // 点的Y坐标            // 判是否在v[0]v[1]和v[2]v[3]两边的同侧            cross1 = (pointX - vertexArray[0].X) * (vertexArray[1].Y - vertexArray[0].Y) - (pointY - vertexArray[0].Y) * (vertexArray[1].X - vertexArray[0].X);            cross2 = (pointX - vertexArray[3].X) * (vertexArray[2].Y - vertexArray[3].Y) - (pointY - vertexArray[3].Y) * (vertexArray[2].X - vertexArray[3].X);            if ((cross1 * cross2) > 0 || (cross1 == 0 && cross2 > 0) || (cross2 == 0 && cross1 > 0))                return false;            // 判是否在v[0]v[3]和v[1]v[2]两边的同侧            cross1 = (pointX - vertexArray[0].X) * (vertexArray[3].Y - vertexArray[0].Y) - (pointY - vertexArray[0].Y) * (vertexArray[3].X - vertexArray[0].X);            cross2 = (pointX - vertexArray[1].X) * (vertexArray[2].Y - vertexArray[1].Y) - (pointY - vertexArray[1].Y) * (vertexArray[2].X - vertexArray[1].X);            if ((cross1 * cross2 > 0) || (cross1 == 0 && cross2 > 0) || (cross2 == 0 && cross1 > 0))                return false;            return true;

再使用DotTrace监测,果然时间消耗瓶颈已经不在这里。

  • * 用数学方法解决工程问题系列(一) 在Winform里画旋转矩形 *
  • * 用数学方法解决工程问题系列(二) 两个矩形(多边形)的碰撞检测 *
  • * 用数学方法解决工程问题系列(三) 判断任意给定一点是否在多边形内 *
  • * 用数学方法解决工程问题系列(四) 计算包围一组多边形的几何形状 *
0 0
原创粉丝点击