百度地图之收索视野内的建筑物
根据用户移动地图的位置,显示在视野范围内的建筑物,简单的思路是,添加地图监听,当地图移动结束之后,计算出当前屏幕四个角的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
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;
}
}
}
}
- WSP Global品牌升级 启用3声母域名
- 一、爬虫基本原理
- python 中__setattr__, __getattr__,__getattribute__, __call__使用方法
- 量子技术与人工智能:同时进化的双生子
- TCP协议三次握手与四次挥手通俗解析
- Silverlight/aspx/ajax/mvc的UI自动化测试
- Office Open XML学习(1)-创建excel文档,并向单元格中插入字符串
- PyMC3和Theano代码构建贝叶斯深度网络,61页PPT探索贝叶斯深度学习以及实现
- 男程序员是不是都不会和女生表达交流?程序员的回答歪了
- Silverlight Telerik控件学习:主题Theme切换
- Silverlight自定义类库实现应用程序缓存
- Silverlight Telerik控件学习:TreeView数据绑定并初始化选中状态、PanelBar的Accordion效果、TabPanel、Frame基本使用
- 这或许是对小白最友好的python入门了吧——4,列表
- 每个人都应该知道的十个机器学习常识
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 这年头还不会SpringBoot?
- PB级大规模Elasticsearch集群运维与调优实践
- 长假慢学,用TensorFlow做了个AI游戏
- 微服务平台之API授权
- 一些让人恶心的代码片段
- 一个依赖搞定 Spring Boot 反爬虫,防止接口盗刷!
- 还在用Swagger(丝袜哥)生成接口文档?我推荐你试试它...
- 技术分享 | 企业版监控工具 MEM 初探
- Java自动化测试(TestNg 10)
- LeetCode109:有序列表转二叉搜索树
- docker和docker-compose
- IDA-完整解析sig
- 干货 | 携程度假无线前端架构演进之路
- Python加速运行技巧
- React 中请求远程数据的四种方法