百度地图之收索视野内的建筑物

根据用户移动地图的位置,显示在视野范围内的建筑物,简单的思路是,添加地图监听,当地图移动结束之后,计算出当前屏幕四个角的GeoPoint,根据这4个点,通过mysql的spatial中的函数,完成在此范围内的建筑物的查询。

1.   mysql spatial介绍

  从MySQL4.0开始加入了Spatial扩展功能,实现了OpenGIS规定的几何数据类型,在SQL中的简单空间运算。但是MySQL对空间查询的支持不够完善,要进行复杂的空间运算,建议使用postgreSQL数据库的postGIS。

    下图是MySQL Spatial接口及类的结构(有背景颜色的框代表接口):

    有关mysql的详细介绍,可以参考一下链接中的文章。

l  官方参考文档(中文):

http://dev.mysql.com/doc/refman/5.1/zh/spatial-extensions-in-mysql.html#mysql-spatial-datatypes

l  官方参考文档(英文):

http://dev.mysql.com/doc/refman/5.0/en/spatial-extensions.html

关于hibernate支持mysql-spatial

http://blog.csdn.net/b10090120/article/details/8698787

http://www.hibernatespatial.org/tutorial.html

拓展mysqlspatial函数:

1)  空间中的点是否相等

DELIMITER $$  
 
CREATE DEFINER = 'smart'@'localhost' 
FUNCTION ArePointsEqual(p1 POINT,  
                        p2POINT  
                        )  
RETURNS TINYINT(1)  
DETERMINISTIC  
NO SQL  
BEGIN  
  RETURN IsZero(x(p1) -x(p2)) AND IsZero(y(p1) - y(p2));  
END  
$$  
 
DELIMITER ;  

2)  查找区域的中心点

USE smartu;  
 
DELIMITER $$  
 
CREATE DEFINER = 'smart'@'localhost' 
FUNCTION GetCenterPoint(g GEOMETRY)  
RETURNS POINT  
DETERMINISTIC  
NO SQL  
BEGIN 
 DECLARE envelope  POLYGON;  
 DECLARE sw, ne    POINT; #South-West and North-East points  
 DECLARE lat, lng  DOUBLE;  
 
 SET envelope =exteriorring(Envelope(g));  
 SET sw =pointn(envelope, 1);  
 SET ne =pointn(envelope, 3);  
 SET lat = x(sw) + (x(ne)- x(sw)) / 2;  
 SET lng = y(sw) + (y(ne)- y(sw)) / 2;  
 RETURN POINT(lat, lng);  
END 
$$  
 
DELIMITER ;  

3)  LineN

USE smartu;  
 
DELIMITER $$  
 
CREATE DEFINER = 'smart'@'localhost' 
FUNCTION LineN(ls LINESTRING,  
               n  INT 
               )  
RETURNS LINESTRING  
DETERMINISTIC  
NO SQL  
BEGIN 
  IF n >= numpoints(ls)THEN 
 RETURN NULL;  
 END IF;  
  RETURNLineString(pointn(ls, n), pointn(ls, n + 1));  
END 
$$  
 
DELIMITER ;  

4)  计算两点间的空间距离

USE smartu;  
 
DELIMITER $$  
 
CREATE DEFINER = 'smart'@'localhost' 
FUNCTION DISTANCE(lat1 DOUBLE,  
                  lon1DOUBLE,  
                  lat2DOUBLE,  
                  lon2DOUBLE  
                  )  
RETURNS DOUBLE 
DETERMINISTIC  
NO SQL  
COMMENT 'counts distance (km) between 2 points on Earth surface' 
BEGIN 
 DECLARE dtor DOUBLEDEFAULT 57.295800;  
 
 RETURN (6371 *acos(sin(lat1 / dtor) * sin(lat2 / dtor) +  
  cos(lat1 / dtor) *cos(lat2 / dtor) *  
  cos(lon2 / dtor - lon1 /dtor)));  
END 
$$  
 
DELIMITER ;  

5)  是否为0

USE smartu;  
 
DELIMITER $$  
 
CREATE DEFINER = 'smart'@'localhost' 
FUNCTION IsZero(n DOUBLE)  
RETURNS TINYINT(1)  
DETERMINISTIC  
NO SQL  
BEGIN 
 DECLARE epsilon DOUBLEDEFAULT 0.00000000001;  
 
 RETURN (abs(n) <=epsilon);  
END 
$$  
 
DELIMITER ;  

2.  项目前台、后台的实现

1)  项目后台实现

l  数据库设计

--创建表 
createtable smart_u_convenience_item_spatial(  
    item_spatial_id varchar(36) not null,  
    location point not null,  
    latitude varchar(20),  
    longitude varchar(20),  
    convenience_item_code varchar(500),  
    convenience_item_name varchar(500),  
 primary key (`item_spatial_id`),  
    spatial key `sp_index`(location)  
)ENGINE=MyISAM;  
--往表中插入数据 
INSERTINTO smart_u_convenience_item_spatial  
SELECTt.convenience_item_id  
     , PointFromText(concat('POINT(',t.item_latitude, ' ', t.item_longitude, ')'))  
     , t.item_latitude  
     , t.item_longitude  
     , t.convenience_item_code  
     , t.convenience_item_name  
 from smart_u_convenience_item t;  

l  后台代码使用到的查询点的sql

SELECT *  
FROM 
  (SELECT *  
 FROM 
    smart_u_convenience_item t  
 WHERE 
     t.convenience_item_idIN  
    (SELECTs.item_spatial_id  
 FROM 
        smart_u_convenience_item_spatial s  
 WHERE 
        intersects(location,  
                   geomfromtext(concat('POLYGON((', 3.9921123E7, ' ', 1.16365462E8,  
 ',', 3.9921123E7, ' ', 1.16441881E8,  
 ',', 3.9879484E7, ' ', 1.16441881E8,  
 ',', 3.9879484E7, ' ', 1.16365462E8,  
 ',', 3.9921123E7, ' ', 1.16365462E8,'))'))))) t  
ORDER BY 
 item_longitude ASC 

2)  前台设计

MKMapViewListener mapViewListener = new MKMapViewListener() {  
 
 @Override 
 public void onMapMoveFinish() {  
 // 此处可以实现地图移动完成事件的状态监听 
            Log.e(TAG,"mapMoveFinish");  
           BsnsDisAllActivity.this.getBsnsDisInfo(BsnsDisAllActivity.this.getGeoPointMap());             
         }  
 
 @Override 
 public void onClickMapPoi(MapPoipoi) {  
            Log.e(TAG,poi.geoPt.getLatitudeE6()+","+poi.geoPt.getLongitudeE6());           
         }  
 
 @Override 
 public void onGetCurrentMap(Bitmaparg0) {  
            Log.e(TAG,"onGetCurrentMap");  
 
         }  
 
 @Override 
 public void onMapAnimationFinish(){  
            Log.e(TAG,"onMapAnimationFinish");  
           BsnsDisAllActivity.this.getBsnsDisInfo(BsnsDisAllActivity.this.getGeoPointMap());  
         }  
      };  
      mMapView.regMapViewListener(app.mBMapManager,mapViewListener);  
 
private Map<String,Double> getGeoPointMap(){  
 
         Projectionprojection = mMapView.getProjection();  
 
         Map<String,Double>polygon = newHashMap<String,Double>();  
         GeoPointtop = projection.fromPixels(0, 0);  
         polygon.put("top_x",(double) top.getLatitudeE6());  
         polygon.put("top_y",(double)top.getLongitudeE6());  
         GeoPointright = projection.fromPixels(mMapView.getWidth(), 0);  
         polygon.put("right_x",(double)right.getLatitudeE6());  
         polygon.put("right_y",(double)right.getLongitudeE6());  
         GeoPointdown = projection.fromPixels(mMapView.getWidth(), mMapView.getHeight());  
         polygon.put("down_x",(double)down.getLatitudeE6());  
         polygon.put("down_y",(double)down.getLongitudeE6());  
         GeoPointleft = projection.fromPixels(0, mMapView.getHeight());  
         polygon.put("left_x",(double)left.getLatitudeE6());  
         polygon.put("left_y",(double)left.getLongitudeE6());  
 
 return polygon;  
      }  
 
 
private voidgetBsnsDisInfo(Map<String,Double>polygon){  
 final Map<String,Double> tPolygon =polygon;  
 new Thread(){  
 public void run() {  
 try{  
                   List<OrderByEntity>orderByEntity = new ArrayList();  
                   OrderByEntityorder = newOrderByEntity();  
                   order.setOrderCol("item_longitude");  
                   order.setOrderType("asc");  
                   orderByEntity.add(order);  
 //              OrderByEntityorder2 = new OrderByEntity(); 
 //              order.setOrderCol("item_latitude"); 
 //              order.setOrderType("asc"); 
 //              orderByEntity.add(order2); 
 
                   ConvenienceItemAckEntityack = SUService.getInstance().getMapBsns(app.nowUser, tPolygon, orderByEntity, null, null);  
                   Log.i(TAG,ack.getAckCode().toString());  
                   Log.i(TAG,ack.getAckMsg().toString());  
                  Message msg = new Message();  
 if(ack.getAckCode().toString().indexOf("INFO") != -1){  
                      msg.what = RESULT_BSNS_CAT;  
                   }else{  
                      msg.what = RESULT_ERROR;  
                   }  
                   msg.obj = ack;  
                   myHandler.sendMessage(msg);  
                }catch(Exception e){  
 
                }  
 
            };  
         }.start();  
      }  
 
       Handler myHandler = new Handler(){  
 public void handleMessage(Messagemsg) {  
 switch (msg.what) {  
 case RESULT_BSNS_CAT:  
                ConvenienceItemAckEntityack = (ConvenienceItemAckEntity)msg.obj;  
                pinItemMark(ack.getResults());  
 break;  
 
 default:  
 break;  
            }  
         };  
      };  
 
 private voidpinItemMark(List<ConvenienceItemEntity> itemList){  
         convenieceItemList= newArrayList<ConvenienceItemEntity>();  
         mGeoList.clear();  
         latLoc.clear();  
 for(inti=0;i<itemList.size();i++){  
            ConvenienceItemEntityitemEntity = itemList.get(i);  
 int lat = Integer.parseInt(itemEntity.getItemLatitude());  
 int loc = Integer.parseInt(itemEntity.getItemLongtude());  
            OverlayItemitem = newOverlayItem(newGeoPoint(lat, loc),itemEntity.getConvenienceItemName() ,itemEntity.getConvenienceItemId());  
 
            ViewdrawableView = LayoutInflater.from(BsnsDisAllActivity.this).inflate(  
                   R.layout.map_drawable_pin, null);// 获取要转换的View资源 
            TextViewTestText = (TextView)drawableView.findViewById(R.id.map_drawable_text);  
            TestText.setText(item.getTitle());//将每个点的Title在弹窗中以文本形式显示出来      
 
            BitmapdrawableBitmap = convertViewToBitmap(drawableView);  
 
            Drawabledraw = newBitmapDrawable(drawableBitmap);  
 
            item.setMarker(draw);  
 
            convenieceItemList.add(itemEntity);  
            mGeoList.add(item);  
            PointlocPoint = newPoint();  
            locPoint.x = i+1;  
            locPoint.y = lat;  
            latLoc.add(locPoint);           
         }  
 
         addMarker(mGeoList);  
 for (int i = 0; i < latLoc.size(); i++){   
 for (int j = 1; j < latLoc.size() - i; j++) {  
                   Point p1 = latLoc.get((j-1));  
                   Point p2 = latLoc.get(j);  
 
 if(p1.y>p2.y){  
                      Point temp = p1;  
                      latLoc.set(j-1, p2);  
                      latLoc.set(j, p1);  
                   }  
 if(latLoc.get(j-1).x==0){  
                      selectedItemLat = j-1;  
                   }  
                 }  
         }  
      }  

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏乐沙弥的世界

SQL server 2005 PIVOT运算符的使用

        PIVOT,UNPIVOT运算符是SQL server 2005支持的新功能之一,主要用来实现行到列的转换。本文主要介绍PIVOT运算符的操作,...

9020
来自专栏杨建荣的学习笔记

通过pl/sql来格式化sql(r4笔记第63天)

在之前的一篇博文中分享了通过java来格式化sql,http://blog.itpub.net/23718752/viewspace-1444910/ 今天突然...

35940
来自专栏大内老A

T-SQL Enhancement in SQL Server 2005[上篇]

较之前一版本,SQL Server 2005可以说是作出了根本性的革新。对于一般的编程人员来说,最具吸引力的一大特性就是实现了对CLR的寄宿,使我们可以使用任意...

21450
来自专栏java一日一条

数据库性能优化之SQL语句优化

在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着...

20620
来自专栏me的随笔

T-SQL基础(二)之关联查询

表运算符的作用是把为其提供的表作为输入,经过逻辑查询处理,返回一个表结果。SQL Server支持四个表运算符:JOIN、APPLY、PIVOT、UNPIVOT...

15210
来自专栏文渊之博

DATETIME类型和BIGINT 类型互相转换

项目中使用BIGINT来存放时间,以下代码用来转换时间类型和BIGINT类型 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIE...

24780
来自专栏me的随笔

T-SQL基础(二)之关联查询

表运算符的作用是把为其提供的表作为输入,经过逻辑查询处理,返回一个表结果。SQL Server支持四个表运算符:JOIN、APPLY、PIVOT、UNPIVOT...

11340
来自专栏数据和云

案例分析:倾斜值传入导致 SQL 资源消耗升高

作者 | 邓秋爽:云和恩墨技术工程师,有超过七年超大型数据库专业服务经验,擅长 Oracle 数据库优化、SQL 优化和 Troubleshooting。

14440
来自专栏杨建荣的学习笔记

和Null有关的函数(r3笔记第48天)

关于null相关的函数在日常的工作中还有比较实用的,可能会碰到各种和Null校验相关的情况,大体有以下几种。 case when decode nvl nvl...

332120
来自专栏WindCoder

where in与join 查询

Oracle:当前所用版本中,限制in中的参数不能超过 1000个。当超出时会被报错"ORA-01795异常(where in超过1000)的解决"。

50800

扫码关注云+社区

领取腾讯云代金券