前言

昨天写了好久的博文我没保存,今天在来想继续写居然没了,气死人啊这种情况你们见到过没,所以今天重新写,我还是切换到了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的世界奥秘----点和线的世界的更多相关文章

  1. 带你剖析WebGis的世界奥秘----点和线的世界(转)

    带你剖析WebGis的世界奥秘----点和线的世界 转:https://zxhtom.oschina.io/zxh/20160813.html  编程  java  2016/08/13 0留言, 0 ...

  2. 带你剖析WebGis的世界奥秘----Geojson数据加载(高级)(转)

    带你剖析WebGis的世界奥秘----Geojson数据加载(高级) 转:https://zxhtom.oschina.io/zxh/20160819.html  编程  java  2016/08/ ...

  3. 带你剖析WebGis的世界奥秘----瓦片式加载地图(转)

    带你剖析WebGis的世界奥秘----瓦片式加载地图 转:https://zxhtom.oschina.io/zxh/20160805.html  编程  java  2016/08/05 0留言,  ...

  4. 带你剖析WebGis的世界奥秘----Geojson数据加载(高级)

    前言:前两周我带你们分析了WebGis中关键步骤瓦片加载+点击事件(具体的看前两篇文章),下面呢,我带大家来看看Geojson的加载及其点击事件 Geojson数据解析 GeoJSON是一种对各种地理 ...

  5. 带你剖析WebGis的世界奥秘----瓦片式加载地图

    WebGIS应用程序的页面能够通过HTML.JSP.ASP或任何任何类型的Web页文件构成,其特殊之处在于,它的请求提交的方法并不是通过常用的 "超链接"形式,而是使用鼠标与Web ...

  6. 笔者带你剖析轻量级Sharding中间件——Kratos1.x

    之所以编写Kratos其实存在一个小插曲,当笔者满山遍野寻找成熟.稳定.高性能的Sharding中间件时,确实是翻山越岭,只不过始终没有找到一款合适笔者项目场景的中间件产品.依稀记得当年第一款使用的S ...

  7. 笔者带你剖析淘宝TDDL(TAOBAO DISTRIBUTE DATA LAYER)

    注:本文部分内容引用本人博客http://gao-xianglong.iteye.com/blog/1973591   前言 在开始讲解淘宝的TDDL(Taobao Distribute Data L ...

  8. 带你剖析淘宝TDDL——Matrix层的分库分表配置与实现

    前言 在开始讲解淘宝的TDDL(Taobao Distribute Data Layer)技术之前,请允许笔者先吐槽一番.首先要开喷的是淘宝的社区支持做的无比的烂,TaoCode开源社区上面,几乎从来 ...

  9. 《笔者带你剖析Apache Commons DbUtils 1.6》(转)

    前言 关于Apache的DbUtils中间件或许了解的人并不多,大部分开发人员在生成环境中更 多的是依靠Hibernate.Ibatis.Spring JDBC.JPA等大厂提供的持久层技术解决方案, ...

随机推荐

  1. java高并发系列-第1天:必须知道的几个概念

    java高并发系列-第1天:必须知道的几个概念 同步(Synchronous)和异步(Asynchronous) 同步和异步通常来形容一次方法调用,同步方法调用一旦开始,调用者必须等到方法调用返回后, ...

  2. WPF 入门笔记之布局

    一.布局原则: 1. 不应显示的设定元素的尺寸,反而元素可以改变它的尺寸,并适应它们的内容 2. 不应使用平布的坐标,指定元素的位置. 3. 布局容器和它的子元素是共享可以使用的空间 4. 可以嵌套的 ...

  3. 多线程总结-同步之synchronized关键字

    目录 1.为什么要使用synchronized? 2.synchronized锁什么,加锁的目的是什么? 3.代码示例 3.1锁this和临界资源对象 3.2锁class类对象 3.3 什么时候锁临界 ...

  4. 一篇文章学会Docker命令

    目录 简介 镜像仓库 login pull push search 本地镜像管理 images rmi tag build history save load import 容器操作 ps inspe ...

  5. Windows OS添加USB3.0驱动!

    原因:现在的win7.win2008等一些早期的系统在安装时无法使USB鼠标和键盘... 1.  素材(dism64工具.UltraISO工具.U盘一个) 2.  先使用UltrISO工具制作一个wi ...

  6. How to Read a Paper丨如何阅读一篇论文

    这是我在看论文时无意刷到的博客推荐的一篇文章"How to Read a Paper",教你怎么样看论文.对于研究生来说,看论文基本是日常,一篇论文十多二十页,如何高效地读论文确实 ...

  7. Spring mybatis 之-ssm框架环境搭建(方案一)

    SSM框架- S-Spring  S-Spring mvc M-mybatis  就需要以下几个配置文件,放在resources文件夹下面: db.properties 放的是数据库连接池的配置文件, ...

  8. UVA1103 古代象形符号 Ancient Messages 题解

    题目链接: https://www.luogu.org/problemnew/show/UVA1103 题目分析: 我们可以先进行矩阵的还原 for(int k=1;k<=4;k++) { a[ ...

  9. Kafka工作流程分析

    Kafka工作流程分析 生产过程分析 写入方式 producer采用推(push)模式将消息发布到broker,每条消息都被追加(append)到分区(patition)中,属于顺序写磁盘(顺序写磁盘 ...

  10. [leetcode]python 448. Find All Numbers Disappeared in an Array

    Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and ot ...