带你剖析WebGis的世界奥秘----点和线的世界(转)
带你剖析WebGis的世界奥秘----点和线的世界
转:https://zxhtom.oschina.io/zxh/20160813.html
本文于538天之前发表,文中内容可能已经过时。
前言
昨天写了好久的博文我没保存,今天在来想继续写居然没了,气死人啊这种情况你们见到过没,所以今天重新写,我还是切换到了HTML格式的书写上大笑。废话不多说了,我们现在就进入主题,上周我仔细研究了WebGis基于openlayers的显示问题,同事也略微的实现了地图上的点击事件当然啦,这周我们将细分为点和线的点击事件,如果读者有兴趣也可以自己研究区域的点击事件,说白了就是我们初中时候学的那个三维立体的思想,或者读者也可以私下找我交流。
逻辑思想
(点)在处理这些点击事件中我突然想到一个很常见的思路,就是我通过点击来获取屏幕的坐标,然后在将屏幕的坐标转换成对应地图上的经纬度,拿到经纬度之后去和数据库里面一条一条匹配,最后从数据查到这个点了我就将这个点的信息给输出,如果我没有查到这个点就说明我没有点击到这个点上。但是值得注意的一点就是我们地图在屏幕上是很小的,是存在点击误差的,什么叫点击误差就是我们点击地图上的点我们肉眼上觉得是点击了点,但是实际上我们点击的那个点的坐标和地图上的那个点的坐标是存在一定的误差的,所以我为了实现肉眼上的点击点的事件,我在查找数据库的时候给定了一个我们肉眼默认的误差范围的,也就是说我在数据中并不是真正去查这个点,而是查询数据库中的点到我这个店的距离的,只要这个距离小于我指定的误差值,我就默认为这两个点是同一个点,这也就是我实现点的思路;那么问题来了如果我在地图上点击的时候出现了两个点都和我这个点的距离在我的误差范围之内呢,答案是肯定会的,那么有的读者会问,这个该怎么办呢。不用担心我有解决方法。在取到不止两个的情况下我们去距离最小的那一个,离的最近的我们默认选择这个点的
(线)处理完点自然就是线了,在处理线的时候我一开始的思路就是拿角度去比对,如果是统一角度的就说明我们点击的点在这条线上面,如果不是统一角度就不在这条线上,这个方法后来我实行了,当然这个也是存在误差的,我指定好了误差之后就可行的,但是在性能上不好,没有在距离的方法有效,因为如果我们用角度的话,角度会根据大小的不同误差级别,也就是说角度本身就有误差,在加上我们的肉眼的误差这样就相当于放大了误差,所以最后在项目里我放弃了角度的方法,后来我换了一种思路,我可以求点到直线的距离啊,这样我就成功的将角度的问题转换成了上面的距离的问题了,而且高中我们都会用点到直线的距离公式,而且俩个点确定直线的方程我们也都会使用最后整理了一下就是下面的代码来实现球点到直线的距离,拿到了距离了就回归了我们上面的点的处理中了,我们只要指定误差范围就可以了。
(总结)理论呢就是这么多,估计有的同学已经开始着急了,怎么还没有代码啊,个人觉得!授人以渔不如授人以渔。所以我在上面才唠叨半天,只要你们理解我的思路,下面的代码只需要有初中的水平就可以看得懂了。
/续上/
代码实现
1、在map地图上我们注册点击事件,唯一不同的是我们在这里自行区分点线
map.events.register(“click”, map, function(e) {
//编写点击事件
}
2、获取屏幕坐标从而转向地理坐标
var lonlat = map.getLonLatFromPixel(e.xy);
3、通过地理坐标去和已有的数据进行匹配查询,这里说的已有数据是说数据库中已经存在的点和线的数据,我现在js模拟一下数据库的写法(data就是数据里的数据)
if(data.length>1){
var min=getDis(data[0].x, data[0].y, data[1].x, data[1].y, lonlat.lon, lonlat.lat);
var index=0;
for(var i=0;i<data.length;i++){
if(i<data.length-1){
var fx = data[i].x;
var fy = data[i].y;
var tx = data[i+1].x;
var ty = data[i+1].y;
}
var dis = getDis(fx, fy, tx, ty, lonlat.lon, lonlat.lat);
if(dis<min){ min="dis;" index="i;" }="" var="" wc="judgediswc(map.getZoom());" if(wc="">=min){
//在误差范围内,可以认为是同一线
var lineName = data[index].site_name+">"+data[index+1].site_name;
//alert(lineName);
$("#qds").val(lineName);
}else{
searRailLine(lonlat.lon, lonlat.lat);
}
}else{
searRailLine(lonlat.lon, lonlat.lat);
}
4、这里提到的getDis 和 judgediswc 还有searRailLine这几个方法都是自己去写的,他们的作用是分别计算点到直线的距离、点到直线距离和误差的比较、去真实数据库查找线的方法。下面进行这三个方法的讲解
4-1、获得点到直线的距离,这个就是我们初高中经常用到的点到直线距离公式,自己稍加推到就可以看得懂了,这个没有什么技术含量,只有别把坐标位置放错了,就可以了,这个返回的dis就是我们需要的距离。这个算法我在数据里也封装好了,待会最后我会帖进来的。
function getDis(fx,fy,tx,ty,lon,lat){
var dis = 637800.138 (
Math.abs(
(
(ty - fy) lon
) + (
(fx -
tx)
lat
) + tx fy - ty * fx
)
) / (
Math.pow(
(ty
- fy) * (ty - fy) + (fx -
tx) * (fx -
tx),
0.5
)
);
return dis;
}
4-2、误差的大小(由于地图的缩放级别不同,我们的误差也不同,这个在前面的理论中我已经解释过了,这个就不多说了)这个就返回我们肉眼能够接受的误差最大值
function judgediswc(level){
var dis=0;
var angle=0;
if(level==15){
dis=12;
angle=42;
}else if(level==14){
dis=16;
angle=94;
}else if(level==13){
dis=52;
angle=149;
}else if(level==12){
dis=69;
angle=403;
}else if(level==11){
dis=178;
angle=479;
}else if(level==10){
dis=294;
angle=1093;
}else if(level==9){
dis=682;
angle=1449;
}else if(level==8){
dis=1488;
angle=4143;
}else if(level==7){
dis=3521;
angle=4617;
}else if(level==6){
dis=6636;
angle=5265;
}else if(level==5){
dis=7051;
angle=30217;
}else if(level==4){
dis=25763;
angle=68126;
}else if(level==3){
dis=60342;
angle=120000;
}else if(level==2){
dis=88189;
angle=220000;
}else if(level==1){
dis=110189;
angle=1000000;
}
return angle;
}
4-3、下面的方法我们就是真正去数据库查找的,上面的方法没有实际用处,只是为了掩饰给读者的快捷方法(注意我ajax的传参 很重要)
function searRailLine(lon,lat){
var sus = function(json, status) {
//alert();
var lineName = json.map[0].station_name+”站”+”>”+json.map[0].next_name+”站”;
$(“#qds”).val(lineName);
siteJson = json.map;
};
AjaxUtil.ajaxCon(path + “/echartMap/selectLineNameStr.json”, {lon:lon,lat:lat,angle:judgediswc(map.getZoom())},
sus);
}
5、具体的三层架构实现我就不写了,相信能看到这里的孩子们三层架构一定都了解。我直接贴sql语句(x,y,z分别是经度、纬度、地图的显示级别)方法中返回的是点到直线的最小距离(有可能有很多个直线都是符合的我们取最小的那个)
SELECTline_name,station_name,station_x,station_y,next_name,next_x,next_y,tFROM(SELECTline_name,station_name,station_x,station_y,next_name,next_x,next_y,637800.138 (ABS(((station_y - next_y) #{x}) + ((next_x -station_x) *
#{y}
) + station_x * next_y - station_y * next_x
)
) / (
POWER(
(station_y
- next_y) * (station_y - next_y) + (next_x -
station_x) * (next_x -
station_x),
0.5
)
) AS t
FROM
rail_line
) AS t
WHERE
t
< #{angle}
AND station_y >= #{y}
AND next_y <= #{y}
order by t asc limit 0,1
</select>
6、有的读者会问了,说好的点和线呢,你的点呢,别着急啊,我先把难的讲完简单,点呢我就把sql语句贴出来,返回了距离的值,在后台你想怎么办就怎么办,那就看你自己了。对吧
<![CDATA[SELECTt.nameFROM(SELECTx.name,ROUND(6378.138 2 ASIN(SQRT(POW(SIN((#{y} PI()/ 180 - y PI() / 180) / 2),2) + COS(
#{y} * PI() / 180) * COS(y *
PI() / 180
) * POW(
SIN(
(
#{x} * PI() / 180 - x * PI() / 180
) / 2
),
2
)
)
) * 1000
) AS dis
FROM
(select SITE_NAME name ,fx x,fy y from TKYZ_BASE
UNION
select SITE_NAME name,fx x,fy y from THYZ_BASE
UNION
select SITE_NAME name,fx x,fy y from TKHYZ_BASE
UNION
select SITE_NAME name,fx x,fy y from TYXHR_BASE
UNION
select SITE_NAME name,fx x,fy y from TBZQD_BASE)x
) AS t
WHERE
t.dis BETWEEN 0
AND #{z}
order by t.dis asc limit 1
]]>
</select>
效果贴图
1、途中高亮显示的是模拟的js中的数据,点击高亮部分就会在脚本中查询我模拟的数据
2、点击高亮线路(北京–》北京南–》丰台)跳出相应的线路信息
3、点击非高亮地区会去查询数据库中的数据,就是真正的数据,如果点击在线上了也会弹出线的详细信息
4、如果我们点击在点上面就会 是点的相应信息,就不贴出来了,在高亮的线上我留个bug就是在线的延长线上也是认为在线上的,实际上不应该认为是线上,这点由于时间紧急我当时就没有写,读者有兴趣自己补充,提示一下判断点的位置是否在线的两端的中间就可以了,这个功能在点击非高亮线的sql语句我实现了的,可以参考一下。
总结
研究了openlayers也有两周了,这两周学到的东西很多。学东西一定要从底层学,才可以学到真正的东西。openlayers的几个基本功能我都已经实现了(地图显示+点线点击事件+定位点+定位线+居中显示墨点+手型显示),其他一些实时定位并随地理位置变动而变动的这个功能没有去实现,因为就两周时间,也就这样了,之间走了很多的弯路,所以发出博文希望对学习WebGis的新同学有点帮助
带你剖析WebGis的世界奥秘----点和线的世界(转)的更多相关文章
- 带你剖析WebGis的世界奥秘----点和线的世界
前言 昨天写了好久的博文我没保存,今天在来想继续写居然没了,气死人啊这种情况你们见到过没,所以今天重新写,我还是切换到了HTML格式的书写上.废话不多说了,我们现在就进入主题,上周我仔细研究了WebG ...
- 带你剖析WebGis的世界奥秘----Geojson数据加载(高级)(转)
带你剖析WebGis的世界奥秘----Geojson数据加载(高级) 转:https://zxhtom.oschina.io/zxh/20160819.html 编程 java 2016/08/ ...
- 带你剖析WebGis的世界奥秘----瓦片式加载地图(转)
带你剖析WebGis的世界奥秘----瓦片式加载地图 转:https://zxhtom.oschina.io/zxh/20160805.html 编程 java 2016/08/05 0留言, ...
- 带你剖析WebGis的世界奥秘----Geojson数据加载(高级)
前言:前两周我带你们分析了WebGis中关键步骤瓦片加载+点击事件(具体的看前两篇文章),下面呢,我带大家来看看Geojson的加载及其点击事件 Geojson数据解析 GeoJSON是一种对各种地理 ...
- 带你剖析WebGis的世界奥秘----瓦片式加载地图
WebGIS应用程序的页面能够通过HTML.JSP.ASP或任何任何类型的Web页文件构成,其特殊之处在于,它的请求提交的方法并不是通过常用的 "超链接"形式,而是使用鼠标与Web ...
- 笔者带你剖析轻量级Sharding中间件——Kratos1.x
之所以编写Kratos其实存在一个小插曲,当笔者满山遍野寻找成熟.稳定.高性能的Sharding中间件时,确实是翻山越岭,只不过始终没有找到一款合适笔者项目场景的中间件产品.依稀记得当年第一款使用的S ...
- 笔者带你剖析淘宝TDDL(TAOBAO DISTRIBUTE DATA LAYER)
注:本文部分内容引用本人博客http://gao-xianglong.iteye.com/blog/1973591 前言 在开始讲解淘宝的TDDL(Taobao Distribute Data L ...
- 带你剖析淘宝TDDL——Matrix层的分库分表配置与实现
前言 在开始讲解淘宝的TDDL(Taobao Distribute Data Layer)技术之前,请允许笔者先吐槽一番.首先要开喷的是淘宝的社区支持做的无比的烂,TaoCode开源社区上面,几乎从来 ...
- 《笔者带你剖析Apache Commons DbUtils 1.6》(转)
前言 关于Apache的DbUtils中间件或许了解的人并不多,大部分开发人员在生成环境中更 多的是依靠Hibernate.Ibatis.Spring JDBC.JPA等大厂提供的持久层技术解决方案, ...
随机推荐
- I.MX6 PHY fixup 调用流程 hacking
/********************************************************************************** * I.MX6 PHY fixu ...
- docker -ce(社区免费版)
Docker -ce https://www.cnblogs.com/zhangxiaoyong/p/9706392.html Docker 是世界领先的软件容器平台.开发人员利用 Docker 可以 ...
- 51nod 1011 最大公约数GCD
输入2个正整数A,B,求A与B的最大公约数. 收起 输入 2个数A,B,中间用空格隔开.(1<= A,B <= 10^9) 输出 输出A与B的最大公约数. 输入样例 30 105 输出 ...
- springboot mybatisPlus配置
1.pom依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...
- 不常用的linux命令
不太常用的命令 vipw ##打开密码配置文件 dmesg ##补充说明:kernel会将开机信息存储在ring buffer中.您若是开机时来不及查看信息,可利用dme ...
- 将java程序打包成exe文件
一. 1. 项目右击,导出 jar文件 2. 下一步,选择 3. 完成 二. 1. 下载exe4j,并破解 2. 其他的步骤都好说,我主说这个步骤,一定要讲所有引用的jar包放到里面否则会报找不到文件 ...
- DHCP(五)
DHCP重新登录 在经过发现,提供,选择以及应答阶段后,DHCP客户端每次重新登录网络时,就不需要再发送DHCP DISCOVER发现信息了,而是直接发送包含前一次所分配的IP地址的DHCP REQU ...
- JS 获取鼠标坐标
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 关于Python导入其他目录中的类
在需要导入的某个类的目录中,添加一个__init__.py的文件,
- Pycharm快速复制当前行到下一行Ctrl+D
Pycharm快速复制当前行到下一行Ctrl+D