判断点是否在多边形内

最近项目有个需求,需要在*图区域随机生成一些点然后添加一些特效。

在多边形内随机生成点这个问题可以理解为判断一个点是否在多边形内。为了实现这个功能,我们可以使用以下步骤:

  1. 首先,我们需要确定多边形的边界。这可以通过获取图区域的坐标范围来实现。例如,如果图区域是一个矩形,我们可以获取其左上角和右下角的坐标。
  2. 接下来,我们需要生成一个随机点。这可以通过使用随机数生成器来生成一个介于0和1之间的浮点数,并将其映射到地图区域的坐标范围内来实现。例如,如果我们的地图区域是一个100x100像素的矩形,我们可以生成一个介于0和100之间的整数作为x坐标,以及一个介于0和100之间的整数作为y坐标。
  3. 然后,我们需要判断生成的随机点是否在多边形内。这可以通过检查随机点的每个相邻边是否与多边形的相应边相交来实现。如果所有相邻边都与多边形的相应边相交,那么随机点就在多边形内;否则,它就在多边形外。
  4. 如果随机点在多边形内,我们可以将其添加到结果列表中。然后,我们可以重复步骤2-4,直到我们生成了所需数量的点。
  5. 最后,我们可以将结果列表中的点绘制到地图上,以显示它们的位置。
  6. 但是矩形不常用,多边形常有。

完成后效果如下:

因为项目使用点是d3,所有优先考虑d3.js中多边形库。

d3.polygonArea(polygon)

返回指定多边形的有符号面积。如果多边形的顶点按逆时针顺序排列(假设原点⟨0,0⟩位于左上角),则返回的面积为正;否则为负或零。

d3.polygonCentroid(polygon)

返回指定多边形的中心。

d3.polygonHull(points)

使用安德鲁的单调链算法返回指定点的凸包。返回的凸包表示为包含输入点的子集的数组,按逆时针顺序排列。如果points的元素少于三个,则返回null。

d3.polygonContains(polygon, point)

如果指定的点在指定的多边形内,则返回true。

d3.polygonLength(polygon)

返回指定多边形的周长。

d3-polygon的库很简单,只有5个方法。

  1. 计算多边形面积
  2. 求多边形的中心
  3. 生成一个凸包
  4. 判断点是否在多边形内(但只能支持凸包)
  5. 求多边形点周长

使用后发现第4个方法只能支持凸包,所以不符合要求。 因此,我决定去寻找另一个库,名为point-in-polygon。

point-in-polygon

这是一个由substack创建的库,可以在GitHub上找到:github.com/substack/po...

这个库非常简单,你不需要去安装它,而是直接将代码复制出来即可使用,因为它的代码非常少,只有十几行。你可以花一点时间来理解这段代码。

javascript 复制代码
function (point, vs) {
    var x = point[0], y = point[1];
    var inside = false;
    for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
        var xi = vs[i][0], yi = vs[i][1];
        var xj = vs[j][0], yj = vs[j][1];
        
        var intersect = ((yi > y) != (yj > y))
            && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
        if (intersect) inside = !inside;
    }
    return inside;
};

函数接收两个参数,一个是待判断的点(point),另一个是多边形的顶点数组(vs)。

  1. 首先,从point中提取出点的x和y坐标。
  2. 初始化一个布尔变量inside为false,表示点是否在多边形内部。
  3. 使用for循环遍历多边形的顶点数组vs。
  4. 在每次循环中,获取当前顶点的x和y坐标,以及下一个顶点的x和y坐标。
  5. 计算当前顶点和下一个顶点组成的线段与待判断点构成的直线的交点。如果交点存在,说明待判断点在当前顶点和下一个顶点组成的线段的两侧,因此需要切换inside的值。
  6. 循环结束后,返回inside的值,表示点是否在多边形内部。
相关推荐
以对_13 分钟前
uview表单校验不生效问题
前端·uni-app
程序猿小D1 小时前
第二百六十七节 JPA教程 - JPA查询AND条件示例
java·开发语言·前端·数据库·windows·python·jpa
奔跑吧邓邓子2 小时前
npm包管理深度探索:从基础到进阶全面教程!
前端·npm·node.js
前端李易安2 小时前
ajax的原理,使用场景以及如何实现
前端·ajax·okhttp
汪子熙2 小时前
Angular 服务器端应用 ng-state tag 的作用介绍
前端·javascript·angular.js
Envyᥫᩣ3 小时前
《ASP.NET Web Forms 实现视频点赞功能的完整示例》
前端·asp.net·音视频·视频点赞
bin91537 小时前
【EXCEL数据处理】000010 案列 EXCEL文本型和常规型转换。使用的软件是微软的Excel操作的。处理数据的目的是让数据更直观的显示出来,方便查看。
大数据·数据库·信息可视化·数据挖掘·数据分析·excel·数据可视化
Мартин.7 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
昨天;明天。今天。8 小时前
案例-表白墙简单实现
前端·javascript·css
数云界8 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端