【GIS新探索】算法实现在不规则区域内均匀分布点
1 概要
在不规则区域内均匀分布点,这个需求初看可能不好理解。如果设想一下需求场景就比较简单了。
场景1:在某个地区范围内,例如A市区有100W人口,需要将这100W人口在地图上面相对均匀的标识出来。
场景2:某不规则场馆,需要均匀布置展位,快速生成展位示意图。
场景其他:规则的电线杆、移动基站等模拟生成。
2 设计方案
既然是要求相对均匀的分布,我想到了格网法,即将多边形分割成特定边长的正方形格子,每个格子的中心点作为分布点。
好处:得到的点是绝对均匀的。
难点:需要判断格子是否在多边形范围内。
示意图:

其中1 2 3 4 四个点代表了不规则多边形的外接矩形角点。绿色的点用来算出1 2 3 4点的。
3 实现
第一步先看看模拟区域。

第二步画格子。

第三步标注格子中间的点。

第四步取出在区域范围内的格子中心点。

至此,基本满足了要求,部分格子的位置细节稍作调整就好。

4 代码
第一步,绘制区域,使用的是canvas。
//公共方法,canvas绘制
var drawFunc={
ctx:null,
init:function(domId){
//获取canvas容器
var can = document.getElementById(domId);
//创建一个画布
var ctx = can.getContext('2d');
this.ctx=ctx;
},
drawArea:function(pts,background){
this.ctx.beginPath(); var pt=pts[0];
this.ctx.moveTo(pt[0],pt[1]); for(var i=1;i<pts.length;i++){
var pt=pts[i];
this.ctx.lineTo(pt[0],pt[1]);
}
this.ctx.fillStyle = background;
this.ctx.fill(); this.ctx.closePath();
}, drawPoint:function(point,color,size){
this.ctx.beginPath();
this.ctx.arc(point[0], point[1], size, 0, 2*Math.PI, true); this.ctx.fillStyle =color;
this.ctx.fill(); this.ctx.closePath();
}, drawLine:function(pts,lineWidth,color){
this.ctx.beginPath();
this.ctx.lineWidth=lineWidth; var pt=pts[0];
this.ctx.moveTo(pt[0],pt[1]);
for(var i=1;i<pts.length;i++){
var pt=pts[i];
this.ctx.lineTo(pt[0],pt[1]);
}
this.ctx.strokeStyle = color;
this.ctx.stroke();
}
}
//01 创建不规则多边形
var pts=[];
pts.push([100,400]);
pts.push([800,400]);
pts.push([800,100]);
pts.push([500,100]);
pts.push([500,250]);
pts.push([100,250]);
drawFunc.drawArea(pts,"#cddc39");
第二步,绘制格子。这里有两个步骤,获取外接矩形和根据特定间距绘制格子。
/**
*绘制格网,并返回格网中心点
**/
function buildBox(space,startPt,endPt){
var width=endPt[0]-startPt[0];
var height=endPt[1]-startPt[1]; var y2=endPt[1];
for(var i=0;i<width;i+=space){
var x=startPt[0]+i; var y1=startPt[1]; drawFunc.drawLine([[x,y1],[x,y2]],1,"#eee");
} var x2=endPt[0];
for(var i=0;i<height;i+=space){
var x1=startPt[0];
var y=startPt[1]+i; drawFunc.drawLine([[x1,y],[x2,y]],1,"#eee");
} var points=[]; for(var i=space;i<width;i+=space){
var x=startPt[0]+i-space/2;
for(var n=space;n<height;n+=space){
var y=startPt[1]+n-space/2; points.push([x,y]);
}
} return points;
}
//02 求不规则多边形外接矩形左上右下点
var box=queryMaxMinPt(pts);
//03 以一定的间距绘制格网,并返回格网中心点
var points= buildBox(20,box.startPt,box.endPt);
/*
*求多边形外接矩形左上右下点
*/
function queryMaxMinPt(points){
var x_min=100000000000000;
var x_max=-1; var y_min=100000000000000;
var y_max=-1; for(var i=0;i<points.length;i++){
var pt=points[i]; if(pt[0]<x_min)
x_min=pt[0];
if(pt[0]>x_max)
x_max=pt[0]; if(pt[1]<y_min)
y_min=pt[1];
if(pt[1]>y_max)
y_max=pt[1];
} return {
startPt:[x_min,y_min],
endPt:[x_max,y_max]
} }
第三和四步,查找在区域范围内的格子,并绘制。
/**
*检查点是否在多边形范围内
**/
function checkInside (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;
};
注:checkInside方法来源自Git,地址:https://github.com/substack/point-in-polygon/blob/master/index.js
//04 遍历中心点,判断点是否在范围内
var pointCount=0;
for(var i=0;i<points.length;i++){
var pt=points[i];
if(checkInside(pt,pts)){
drawFunc.drawPoint(pt,"red",2);
pointCount++;
} } console.log("范围内有:"+pointCount+"个点");
以上就是核心的实现代码,如果需要下载源码请移步我的博客下载,地址:
http://www.88gis.cn/web/pages/blog/blogInfo.html?id=38d8959a-f348-41df-b507-6c10e517e7a7
查看更多GIS、WPF、JAVA、前端技术分享,请访问我的个人技术网站,查看更多技术分享。网站地址:www.88gis.cn
【GIS新探索】算法实现在不规则区域内均匀分布点的更多相关文章
- 【原】ios的hitTest方法以及不规则区域内触摸事件处理方法
概述 在正常的使用场景中,我们处理了比较多的矩形区域内触摸事件,比如UIButton.UIControl.一般来说,这些控件的图形以及触摸区域都是矩形或者圆角矩形的.但是在一些特殊应用场景中我们有时不 ...
- ios的hitTest方法以及不规则区域内触摸事件处理方法
概述 在正常的使用场景中,我们处理了比较多的矩形区域内触摸事件,比如UIButton.UIControl.一般来说,这些控件的图形以及触摸区域都是矩形或者圆角矩形的.但是在一些特殊应用场景中我们有时不 ...
- 【GIS新探索】GeoHash原理和编解码实现
1.什么是GeoHash geohash基本原理是将地球理解为一个二维平面,将平面递归分解成更小的子块,每个子块在一定经纬度范围内拥有相同的编码.不好理解,没关系,我来找个图. 就像上面这张图,一个坐 ...
- AS3 在不规则区域内拖动
原理: 1.确保拖动对象在鼠标点上,如果不确定会出现瞬间移动的感觉 2.确保触碰到非通行区域,跳回到没触碰的点 源码: import flash.events.MouseEvent; import f ...
- [OpenGL] 不规则区域的填充算法
不规则区域的填充算法 一.简单递归 利用Dfs实现简单递归填充. 核心代码: // 简单深度搜索填充 (四连通) void DfsFill(int x, int y) { || y < || x ...
- 发表在 Science 上的一种新聚类算法
今年 6 月份,Alex Rodriguez 和 Alessandro Laio 在 Science 上发表了一篇名为<Clustering by fast search and find of ...
- 【Unity游戏开发】UGUI不规则区域点击的实现
一.简介 马三从上一家公司离职了,最近一直在出去面试,忙得很,所以这一篇博客拖到现在才写出来.马三在上家公司工作的时候,曾处理了一个UGUI不规则区域点击的问题,制作过程中也有一些收获和需要注意坑,因 ...
- UGUI实现不规则区域点击响应
UGUI实现不规则区域点击响应 前言 大家吼啊!最近工作上事情特别多,没怎么打理博客.今天无意打开cnblog才想起该写点东西了.今天给大家讲一个Unity中不规则区域点击响应的实现方法,使用UGUI ...
- 课题:html5图像羽化(不规则区域羽化,feather,html5羽化)
下午搜索了一堆相关文章,没有找到符合要求的. 对一张图片应用不规则区域的羽化,该怎么做呢? 首先去查了下 羽化的原理,然而没有什么用, 然后就开始从表现层去研究怎么模拟? idea 1: blur滤镜 ...
随机推荐
- myeclipse 快捷键,从步骤开始的大括号定位到匹配方法结束的大括号
myeclipse 快捷键,从方法开始的大括号定位到匹配方法结束的大括号转至匹配的括号 Ctrl+Shift+P ctr+shift+r 文件名搜索文件 ctr+h 搜索文件里 ...
- C语言基础第一次作业
一,1)大学和高中最大的不同是没有人天天看着你,请问大学理想的师生关系是?有何感想? 看了邹欣老师博客中写到的教学基础——师生关系后陷入沉思,邹欣老师在她的博客中直接否认了传统认知的师生关系——蜡烛, ...
- Gym 101201F Illumination (Two-Sat)
题意:一个n*n的房子,有很多灯,每个格子只能被上下方向照一次.左右方向照一次,每个灯可以选择上下或是左右照,照明长度以自身位置为中心,占用2*r+1个格子.问能否安排一种方案,使所有格子满足条件. ...
- CodeForces 518B Tanya and Postcard (题意,水题)
题意:给定两个字符串,然后从第二个中找和第一个相同的,如果大小写相同,那么就是YAY,如果大小写不同,那就是WHOOPS.YAY要尽量多,其次WHOOPS也要尽量多. 析:这个题并不难,难在读题懂题意 ...
- .NET基础 (13)IFormattable和IformatProvider的使用
IFormattable和IformatProvider的使用1 如何使用IFormattable接口实现格式化输出2 如何告诉类型格式化输出的方式 IFormattable和IformatProvi ...
- IntelliJ IDEA 2016.1.3(64) license server 与汉化
license server:http://idea.iteblog.com/key.php 汉化:将resources_cn.jar 复制到安装IDEA安装目录下的lib文件夹中.重新打开即可. r ...
- 百度地图api描绘车辆历史轨迹图
最近公司在做项目需需求:车辆定位后在地图显示历史轨迹的功能 一开始使用了google的地图api,但是发现会一直关闭,索性支持下国产,使用了百度地图api search方法把两个点连接成线后,会出现起 ...
- MSP430 G2553 比较器Comparator_A+、数据流程图DFD、状态转换图STD
一.CA+构造 MSP430G2553带有一个比较器Comparator_A+(CA+),其构造框图如下图所示. 二.输入 & 输出 如上图所示,比较器有一个同向输入端(V+)和一个反向输入端 ...
- Tempdb--查看TempDB上是否需要增加文件
SELECT [owt].[session_id], [owt].[exec_context_id], [owt].[wait_duration_ms], [owt].[wait_type], [ow ...
- asp.net 导出 Excel
/// <summary> /// List 数据导出Excel /// </summary> /// <param name="list">数 ...