带你剖析WebGis的世界奥秘----点和线的世界

转:https://zxhtom.oschina.io/zxh/20160813.html

 编程  java  2016/08/13 0留言, 0参与 view : 3次

本文于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的世界奥秘----点和线的世界(转)的更多相关文章

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

    前言 昨天写了好久的博文我没保存,今天在来想继续写居然没了,气死人啊这种情况你们见到过没,所以今天重新写,我还是切换到了HTML格式的书写上.废话不多说了,我们现在就进入主题,上周我仔细研究了WebG ...

  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. socketserver模块简介

    1. socketserver模块简介 在python的socket编程中,实用socket模块的时候,是不能实现多个连接的,当然如果加入其 它的模块是可以的,例如select模块,在这里见到的介绍下 ...

  2. InpOutx64 替代 winIOx64

    /***************************************************************************** * InpOutx64 替代 winIOx ...

  3. (效果五)js获取客户端ip地址及浏览器信息

    在前端开发的时候,有时候为了测试需要得到访问客户的ip地址.虽说是后端来做的,但是我们前端也可以完成. 先说下获取用户ip地址,包括像ipv4,ipv6,掩码等内容,但是大部分都要根据浏览器的支持情况 ...

  4. CVS winCVS配置讲解及用户管理

    首先 用到工具包包括 CVSNT ,WinCvs及相关python 2.2.3和TCL832 可点此链接下载 http://files.cnblogs.com/lppblogs/%E6%96%87%E ...

  5. Oracle查询脚本优化

    发现生产环境的Oracle数据库cpu使用率上升超过70%,其中一条查询语句达到每秒调用40多次.现在我们来观摩下该语句: select t.id,t.level,t.policy, t.type,t ...

  6. fragment在水平/垂直时的应用

    直接看代码 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedIns ...

  7. 【转】JMeter代理录制脚本

    JMeter代理录制脚本 使用JMeter代理录制脚本的过程如下: 1.启动JMeter,在测试计划中添加“线程组”. 2.在“线程组”中添加“HTTP请求默认值”,参数设定如下: 3.在“”中添加“ ...

  8. Avro之一:Avro简介

    一.引言 1. 简介 Avro是Hadoop中的一个子项目,也是Apache中一个独立的项目,Avro是一个基于二进制数据传输高性能的中间件.在Hadoop的其他项目中例如HBase(Ref)和Hiv ...

  9. keytool生成JKS证书的详细步骤及截图

    注:防止有不必要的空格,尽量不要复制粘贴 1. 依据CFCA所提供的CN生成密钥存储文件和密钥对(创建JKS证书库) keytool -genkey -v -alias slserver -keyal ...

  10. 1118 Birds in Forest

    题意: 思路:并查集模板题. 代码: #include <cstdio> #include <algorithm> using namespace std; ; int fat ...