带你剖析WebGis的世界奥秘----点和线的世界
前言
昨天写了好久的博文我没保存,今天在来想继续写居然没了,气死人啊这种情况你们见到过没,所以今天重新写,我还是切换到了HTML格式的书写上。废话不多说了,我们现在就进入主题,上周我仔细研究了WebGis基于openlayers的显示问题,同事也略微的实现了地图上的点击事件当然啦,这周我们将细分为点和线的点击事件,如果读者有兴趣也可以自己研究区域的点击事件,说白了就是我们初中时候学的那个三维立体的思想,或者读者也可以私下找我交流。
逻辑思想
(点)在处理这些点击事件中我突然想到一个很常见的思路,就是我通过点击来获取屏幕的坐标,然后在将屏幕的坐标转换成对应地图上的经纬度,拿到经纬度之后去和数据库里面一条一条匹配,最后从数据查到这个点了我就将这个点的信息给输出,如果我没有查到这个点就说明我没有点击到这个点上。但是值得注意的一点就是我们地图在屏幕上是很小的,是存在点击误差的,什么叫点击误差就是我们点击地图上的点我们肉眼上觉得是点击了点,但是实际上我们点击的那个点的坐标和地图上的那个点的坐标是存在一定的误差的,所以我为了实现肉眼上的点击点的事件,我在查找数据库的时候给定了一个我们肉眼默认的误差范围的,也就是说我在数据中并不是真正去查这个点,而是查询数据库中的点到我这个店的距离的,只要这个距离小于我指定的误差值,我就默认为这两个点是同一个点,这也就是我实现点的思路;那么问题来了如果我在地图上点击的时候出现了两个点都和我这个点的距离在我的误差范围之内呢,答案是肯定会的,那么有的读者会问,这个该怎么办呢。不用担心我有解决方法。在取到不止两个的情况下我们去距离最小的那一个,离的最近的我们默认选择这个点的(线)处理完点自然就是线了,在处理线的时候我一开始的思路就是拿角度去比对,如果是统一角度的就说明我们点击的点在这条线上面,如果不是统一角度就不在这条线上,这个方法后来我实行了,当然这个也是存在误差的,我指定好了误差之后就可行的,但是在性能上不好,没有在距离的方法有效,因为如果我们用角度的话,角度会根据大小的不同误差级别,也就是说角度本身就有误差,在加上我们的肉眼的误差这样就相当于放大了误差,所以最后在项目里我放弃了角度的方法,后来我换了一种思路,我可以求点到直线的距离啊,这样我就成功的将角度的问题转换成了上面的距离的问题了,而且高中我们都会用点到直线的距离公式,而且俩个点确定直线的方程我们也都会使用最后整理了一下就是下面的代码来实现球点到直线的距离,拿到了距离了就回归了我们上面的点的处理中了,我们只要指定误差范围就可以了。(总结)理论呢就是这么多,估计有的同学已经开始着急了,怎么还没有代码啊,个人觉得!授人以渔不如授人以渔。所以我在上面才唠叨半天,只要你们理解我的思路,下面的代码只需要有初中的水平就可以看得懂了。
/*续上*/代码实现
<span style="font-size:24px;"><span style="font-size:18px;">1、在map地图上我们注册点击事件,唯一不同的是我们在这里自行区分点线</span>
map.events.register("click", map, function(e) {
//编写点击事件
}</span>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++){
<span style="font-family:SimHei;"> </span>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;
<span style="font-family:SimHei;"> </span>}
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分别是经度、纬度、地图的显示级别)方法中返回的是点到直线的最小距离(有可能有很多个直线都是符合的我们取最小的那个)
<!-- 点在线上的方法啊 -->
<select id="selectLine" resultType="java.util.HashMap">
SELECT
line_name,
station_name,
station_x,
station_y,
next_name,
next_x,
next_y,
t
FROM
(
SELECT
line_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语句贴出来,返回了距离的值,在后台你想怎么办就怎么办,那就看你自己了。对吧
<!-- 获取站名 -->
<select id="selectPosition" resultType="String" parameterType="HashMap">
<![CDATA[
SELECT
t.name
FROM
(
SELECT
x.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的世界奥秘----点和线的世界(转)
带你剖析WebGis的世界奥秘----点和线的世界 转:https://zxhtom.oschina.io/zxh/20160813.html 编程 java 2016/08/13 0留言, 0 ...
- 带你剖析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等大厂提供的持久层技术解决方案, ...
随机推荐
- 【无线安全实践入门】网络扫描和ARP欺骗
文中可能存在错误操作或错误理解,望大家不吝指正. 同时也希望可以帮助到想要学习接触此方面.或兴趣使然的你,让你有个大概的印象. !阅前须知! 本文是基于我几年前的一本笔记本,上面记录了我学习网络基础时 ...
- (转)Java 8 中的 Streams API 详解
为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX 对 ...
- Linux系统下word转pdf,xls转pdf,ppt转pdf
word转换pdf的技术方案,供参考.[doc/docx/ppt/pptx/xls/xlsx均支持转换] 本方案是Java结合shell命令完成,不同于以往的仅依赖java组件转换 ...
- MyBatis从入门到精通:insert用法
2.4.1 简单的insert方法 1.接口类中的方法: int insert(SysUser sysUser); 2.映射文件中的修改: <!-- insert标签包含如下的属性: id: p ...
- SSAS Tabular 表格模型建模(关系)及部署
一.表格建模(SSAS 表格) 表格模型是 Analysis Services 中的内存中数据库. 使用最先进的压缩算法和多线程查询处理器,xVelocity 内存中分析引擎 (VertiPaq) ...
- Contos7 常用命令
```pythoncentos常用命令: 查看所有运行的单元:systemctl list-units 查看所有单元:systemctl list-units --all 查看所有启动的服务:syst ...
- poi解析excel文件报错
getFileMagic() only operates on streams which support mark(int) 使用 bis 解决 BufferedInputStream bis = ...
- [leetcode] 111.Mininum Depth of Binary Tree (Easy)
原题 寻找二叉树最短深度 这里用了dfs,beat 100%,4ms class Solution { public: int minDepth(TreeNode *root, int minNum ...
- SpringBoot(18)---通过Lua脚本批量插入数据到Redis布隆过滤器
通过Lua脚本批量插入数据到布隆过滤器 有关布隆过滤器的原理之前写过一篇博客: 算法(3)---布隆过滤器原理 在实际开发过程中经常会做的一步操作,就是判断当前的key是否存在. 那这篇博客主要分为三 ...
- javaweb入门---web服务器与HTTP协议基础
上文web基础简介了web到底是什么,以及身为Java开发人员需要掌握的地方.本文将解答web服务器是什么,怎么使用?还有关于http协议的基础知识. web服务器 web服务器的大概念很广泛,但是通 ...