百度地图查询视野范围内的建筑物

百度地图   2013-07-15 20:05:14 发布
您的评价:
     
4.5
收藏     2收藏
文件夹
标签
(多个标签用逗号分隔)

   根据用户移动地图的位置,显示在视野范围内的建筑物,简单的思路是,添加地图监听,当地图移动结束之后,计算出当前屏幕四个角的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;
                   }
                 }
         }
      }
来自:http://blog.csdn.net/fengshuiyue/article/details/9155463

扩展阅读

百度地图API的学习
基于百度地图SDK开发的一款交通助手App
Android百度地图之驾车路线的搜索
百度地图的React-Native Android版本
Android百度地图 - 在地图上标注已知GPS纬度经度值的一个或一组覆盖物

为您推荐

跟据经纬度实现附近搜索Java实现
基于LBS功能应用的Geohash方案
利用MySQL数据库来处理中英文取首字母排序
MySQL存储过程详解
让MySQL支持中文排序的实现方法

更多

百度地图
地理信息系统GIS
相关文档  — 更多
相关经验  — 更多
相关讨论  — 更多