计算 一个点 附近的地方

标签: web java 经纬度 距离计算 | 发表时间:2014-08-23 12:33 | 作者:coderbee
出处:http://coderbee.net

问题

随着地理位置的应用普及,越来越多类似计算 一个点 附近的酒店的需求。比如,显示当前位置2000米范围内的 7 天酒店。

一般来说,在系统里都有一张表,存储了每个 7 天酒店的位置信息,表结构可以简化为三个字段 tb_location(ID, lng, lat),其中 lng:表示经度;lat:表示纬度,这两个字段都是数值类型的,且建了索引。

现在要把 2 公里范围内的 7 天酒店找出来,有的人写的 SQL 语句大概是这样的:
select id from tb_location where calc_distance(lng, lat, curLng, curLat) < 2000

这个语句的问题是没法利用索引,需要全表扫描,计算每一条记录与当前位置的距离,效率很低。

优化

用一张图来说明优化策略:
附近地点计算优化

2 公里范围是一个圆,这个圆的边界是由任意多的点确定的。但一个正方形的边界却是由四个点确定的,所以可以通过把要查找的地点限定在包围这个圆的最小正方形来缩小查找范围。

计算代码如下(收集自网络):

  package net.coderbee.gps;

public class GPS {

     private final double EARTH_RADIUS = 6378.137; // 地球半径

     private static double rad(double d) {
          return d * Math.PI / 180.0; // 计算弧长
     }

     /**
     * 计算两个地理坐标之间的距离,
     * 
     * @param Lat1
     * @param Lng1
     * @param Lat2
     * @param Lng2
     * @return 距离,单位是米
     */
     public double calcDistance(double Lat1, double Lng1, double Lat2,
               double Lng2) {
          double radLat1 = rad(Lat1);
          double radLat2 = rad(Lat2);
          double a = radLat1 - radLat2;
          double b = rad(Lng1) - rad(Lng2);
          double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
                    + Math.cos(radLat1) * Math.cos(radLat2)
                    * Math.pow(Math.sin(b / 2), 2)));
          s = s * EARTH_RADIUS;
          s = s * 1000; // 换算成米
          return s;

     }

     /**
     * 计算最小正方形的四个经纬度值
     * 
     * @param lng
     *            经度
     * @param lat
     *            纬度
     * @param distance
     *            距离
     * @return
     */
     public static double[] getRectangle(double lng, double lat, long distance) {
          float delta = 111000;

          double minLng = lng - distance
                    / Math.abs(Math.cos(Math.toRadians(lat)) * delta);
          double maxLng = lng + distance
                    / Math.abs(Math.cos(Math.toRadians(lat)) * delta);
          double minLat = lat - (distance / delta);
          double maxLat = lat + (distance / delta);
          return new double[] { minLng, minLat, maxLng, maxLat };
     }
}

如果需要可以转换为 SQL 的函数。

那么查询的 SQL 语句可以优化为:

  select id from (
     select loc.id, calc_distance(loc.lng,  loc.lat,  :curLng,  :curLat) distance
     from tb_location loc 
     where loc.lng >= :minLng and loc.lng < :maxLng 
          and loc.lat >= :minLat and loc.lat < :maxLat
) t 
where t.distance < 2000

相关 [计算 地方] 推荐:

计算 一个点 附近的地方

- - 码蜂笔记
随着地理位置的应用普及,越来越多类似计算 一个点 附近的酒店的需求. 比如,显示当前位置2000米范围内的 7 天酒店. 一般来说,在系统里都有一张表,存储了每个 7 天酒店的位置信息,表结构可以简化为三个字段. tb_location(ID, lng, lat),其中 lng:表示经度;lat:表示纬度,这两个字段都是数值类型的,且建了索引.

oracle license计算

- Fenng - eagle&#39;s home
Oracle license的计算是基于CPU core的. 用core的数目乘以一个系数core factor就可以得到所需的oracle license的数目. 对于不同的CPU,core factor是不一样的,可以从oracle提供的这张列表中查到 Oracle Processor Core Factor Table.

理解云计算

- 车东 - oneoo&#39;s 私家花园
  现在互联网最热门的关键字“云计算”,大大小小的公司纷纷加入到这块领域. 简单来说,目前的“云计算”主要分为:SaaS、PaaS和IaaS三大类.   其中SaaS云计算,为软件即服务的概念. 把传统客户端软件部署在互联网上,用户只需要一个浏览器就可以使用到软件的模式. 其实早在2000年就已经有B/S结构的软件服务,与现在所说的SaaS云计算相近,但此前的B/S结构软件服务,数据库等服务端是需要用户自行部署的,而非由软件提供商进行统一部署.

钢琴计算器

- 丑秋 - 专利之家-设计发明与创意商机
这款太阳能计算器别出心裁地设计了黑白相间的按键,看起来像钢琴的琴键一样,十分有趣. 或许这样的计算器可以给枯燥的计算工作增添一点乐趣,让它不再乏味.

10问云计算

- - 《商业价值》杂志
与数百位关注和实践云计算的CIO们共同解读云计算热点问题. 被视作IT界第三次革命的云计算,已经从炙手可热的概念逐渐走向了实际应用. 2011年8-11月, ITValue社区联合英特尔公司,与数百位关注和实践云计算的CIO们一起展开深入探讨,话题涉及云计算的商业价值、安全性、开放性、高效性、简单性等方面.

云计算的困局

- Star Ocean - It Talks--上海魏武挥的博客
有个媒体朋友打电话咨询我一个事. 说在江浙一带,有一位搞国际货运代理的民营企业家,想利用云计算来整合各种资源,比如运输车队、仓库、集装箱乃至货船. 这些资源的调配信息对任何一家从事外贸的企业都很重要,如果将这些信息放在所谓的“云”上,并加以运算,这些企业再以各种设备联入这个“云”,这位企业家觉得是一个很有前途的买卖.

开源云计算ERP ErpCore

- Le - 开源中国社区最新软件
  ErpCore是一套强大的云计算ERP开发框架,集数据库设计、软件建模、模型自动生成、界面可视化设计、业务流可自定义、全自动生成用户所需系统于一体. 在此框架上扩展出所有行业的业务系统,它让软件工程师从“建模——写代码——测试”所有繁琐重复的工作变为全自动化生成,大大简化了企业软件的开发时间和成本;同时,使用该框架扩展的所有业务子系统能够无缝连接进行数据共享,这也是云计算ERP的实现基础,杜绝了传统ERP的子.

异构计算的挑战

- Guancheng(冠诚) - 技术改变世界 创新驱动中国 - 《程序员》官网
进入新世纪之后,软件研发面临并行编程的技术变革、硬件架构面临异构计算的挑战,这些改变是否意味着新的机遇,取决于能否建立良好的生态链. 2004年12月,C++标准化委员会主席、著名程序员Herb Sutter在自己的个人网站发表了一篇影响深远的文章《免费午餐已经结束》(中文版发表于本刊2006年11月期).

并行计算的解药

- chengdujin - 牛博山寨 编辑推荐
前几天看到 reddit.com 的 programming 类别第一名是《 Parallelism is Not Concurrency 》. 读完之后发现和我去年的《多核与锁》有很多观点上的共通之处. 《 Parallelism is Not Concurrency 》的开篇行文更流畅幽默,对并发( concurrency )和并行( parallelism )有更精辟的总结.

优秀的Android计算器

- 李龑 - Solidot
Paul Power 写道 "计算器是操作系统自带的基本工具之一. 这些简单的工具提供了满足基本需求所需的足够功能. 但Android设备自带的计算器功能相当有限,仅提供了基本的加减乘除和括号等功能. 这篇介绍了十多款功能丰富的优秀计算器,其中部分还能绘制2D和3D图形,处理复杂的数学函数. 利用这些工具,Android智能手机能变成可随时使用的图形计算器.