首页 > 程序开发 > 移动开发 > Android >

百度地图

2016-08-22

POI即地图注点,它是“Point of Interest”的缩写,在地图上标注地点名称、类别、经度、纬度等信息,是一个带位置信息的地图标注。POI搜索是地图sdk的一个重要应用,根据关键字搜索并在地图上显示POI结果,这是智能出行的基础。

显示地图和定位

对于一个地图SDK来说,首先要显示地图,然后定位到当前城市。

这方面百度地图和高德地图的处理代码差不多,下面是两种地图sdk显示并定位的代码例子:
百度地图
//以下主要是定位用到的代码
privateMapViewmMapView;
privateBaiduMapmMapLayer;
privateLocationClientmLocClient;
privatebooleanisFirstLoc=true;//是否首次定位

privatevoidinitLocation(){
mMapView=(MapView)findViewById(R.id.bmapView);
//先隐藏地图,待定位到当前城市时再显示
mMapView.setVisibility(View.INVISIBLE);
mMapLayer=mMapView.getMap();
mMapLayer.setOnMapClickListener(this);
//开启定位图层
mMapLayer.setMyLocationEnabled(true);
mLocClient=newLocationClient(this);
//设置定位监听器
mLocClient.registerLocationListener(newMyLocationListenner());
LocationClientOptionoption=newLocationClientOption();
option.setOpenGps(true);//打开gps
option.setCoorType("bd09ll");//设置坐标类型
option.setScanSpan(1000);
option.setIsNeedAddress(true);//设置true才能获得详细的地址信息
//设置定位参数
mLocClient.setLocOption(option);
//开始定位
mLocClient.start();
//获取最近一次的位置
//mLocClient.getLastKnownLocation();
}

publicclassMyLocationListennerimplementsBDLocationListener{

@Override
publicvoidonReceiveLocation(BDLocationlocation){
//mapview销毁后不在处理新接收的位置
if(location==null||mMapView==null){
Log.d(TAG,"locationisnullormMapViewisnull");
return;
}
m_latitude=location.getLatitude();
m_longitude=location.getLongitude();
Stringposition=String.format("当前位置:%s|%s|%s|%s|%s|%s|%s",
location.getProvince(),location.getCity(),
location.getDistrict(),location.getStreet(),
location.getStreetNumber(),location.getAddrStr(),
location.getTime());
loc_position.setText(position);
MyLocationDatalocData=newMyLocationData.Builder()
.accuracy(location.getRadius())
//此处设置开发者获取到的方向信息,顺时针0-360
.direction(100).latitude(m_latitude)
.longitude(m_longitude).build();
mMapLayer.setMyLocationData(locData);
if(isFirstLoc){
isFirstLoc=false;
LatLngll=newLatLng(m_latitude,m_longitude);
MapStatusUpdateupdate=MapStatusUpdateFactory.newLatLngZoom(ll,14);
mMapLayer.animateMapStatus(update);
//定位到当前城市时再显示图层
mMapView.setVisibility(View.VISIBLE);
}
}

publicvoidonReceivePoi(BDLocationpoiLocation){
}
}

POI搜索

POI即地图注点,它是“Point of Interest”的缩写,在地图上标注地点名称、类别、经度、纬度等信息,是一个带位置信息的地图标注。POI搜索是地图sdk的一个重要应用,根据关键字搜索并在地图上显示POI结果,这是智能出行的基础。


下面是使用百度地图搜索POI的截图:
\


下面是两种地图sdk进行POI搜索的代码例子:
百度地图
//以下主要是POI搜索用到的代码
privatePoiSearchmPoiSearch=null;
privateSuggestionSearchmSuggestionSearch=null;
privateAutoCompleteTextViewmKey=null;
privateEditTextmScope=null;
privateButtonbtn_search,btn_nextpage,btn_cleardata;
privateArrayAdaptersugAdapter=null;
privateintload_Index=0;

privatevoidinitMap(){
mPoiSearch=PoiSearch.newInstance();
mPoiSearch.setOnGetPoiSearchResultListener(this);
mSuggestionSearch=SuggestionSearch.newInstance();
mSuggestionSearch.setOnGetSuggestionResultListener(this);
mScope=(EditText)findViewById(R.id.poi_city);
mKey=(AutoCompleteTextView)findViewById(R.id.poi_searchkey);
btn_search=(Button)findViewById(R.id.search);
btn_nextpage=(Button)findViewById(R.id.map_next_data);
btn_cleardata=(Button)findViewById(R.id.map_clear_data);
btn_search.setOnClickListener(this);
btn_nextpage.setOnClickListener(this);
btn_cleardata.setOnClickListener(this);
sugAdapter=newArrayAdapter(this,R.layout.spinner_dropdown_item);
mKey.setAdapter(sugAdapter);

//当输入关键字变化时,动态更新建议列表
mKey.addTextChangedListener(newTextWatcher(){

@Override
publicvoidafterTextChanged(Editablearg0){
}

@Override
publicvoidbeforeTextChanged(CharSequencearg0,intarg1,
intarg2,intarg3){
}

@Override
publicvoidonTextChanged(CharSequencecs,intarg1,intarg2,
intarg3){
if(cs.length()<=0){
return;
}
Stringcity=mScope.getText().toString();
//使用建议搜索服务获取建议列表,结果在onGetSuggestionResult中更新
mSuggestionSearch
.requestSuggestion((newSuggestionSearchOption())
.keyword(cs.toString()).city(city));
}
});
}

@Override
publicvoidonGetSuggestionResult(SuggestionResultres){
if(res==null||res.getAllSuggestions()==null){
return;
}else{
sugAdapter.clear();
for(SuggestionResult.SuggestionInfoinfo:res.getAllSuggestions()){
if(info.key!=null){
sugAdapter.add(info.key);
}
}
sugAdapter.notifyDataSetChanged();
}
}

//影响搜索按钮点击事件
publicvoidsearchButtonProcess(Viewv){
Log.d(TAG,"editCity="+mScope.getText().toString()
+",editSearchKey="+mKey.getText().toString()
+",load_Index="+load_Index);
Stringkeyword=mKey.getText().toString();
if(search_method==SEARCH_CITY){
Stringcity=mScope.getText().toString();
mPoiSearch.searchInCity((newPoiCitySearchOption()).city(city)
.keyword(keyword).pageNum(load_Index));
}elseif(search_method==SEARCH_NEARBY){
LatLngposition=newLatLng(m_latitude,m_longitude);
intradius=Integer.parseInt(mScope.getText().toString());
mPoiSearch.searchNearby((newPoiNearbySearchOption())
.location(position).keyword(keyword).radius(radius)
.pageNum(load_Index));
}
}

publicvoidgoToNextPage(Viewv){
load_Index++;
searchButtonProcess(null);
}

publicvoidonGetPoiResult(PoiResultresult){
if(result==null
||result.error==SearchResult.ERRORNO.RESULT_NOT_FOUND){
Toast.makeText(this,"未找到结果",Toast.LENGTH_LONG).show();
return;
}elseif(result.error==SearchResult.ERRORNO.NO_ERROR){
mMapLayer.clear();
PoiOverlayoverlay=newMyPoiOverlay(mMapLayer);
mMapLayer.setOnMarkerClickListener(overlay);
ListpoiList=result.getAllPoi();
overlay.setData(result);
overlay.addToMap();
overlay.zoomToSpan();
//for(PoiInfopoi:poiList){
//Stringdetail=String.format(
//"uid=%s,city=%s,name=%s,phone=%s,address=%s",poi.uid,
//poi.city,poi.name,poi.phoneNum,poi.address);
//Log.d(TAG,detail);//坐标为poi.location(LatLng结构)
//}
}elseif(result.error==SearchResult.ERRORNO.AMBIGUOUS_KEYWORD){
//当输入关键字在本市没有找到,但在其他城市找到时,返回包含该关键字信息的城市列表
StringstrInfo="在";
for(CityInfocityInfo:result.getSuggestCityList()){
strInfo+=cityInfo.city+",";
}
strInfo+="找到结果";
Toast.makeText(this,strInfo,Toast.LENGTH_LONG).show();
}
}

publicvoidonGetPoiDetailResult(PoiDetailResultresult){
if(result.error!=SearchResult.ERRORNO.NO_ERROR){
Toast.makeText(this,"抱歉,未找到结果",Toast.LENGTH_SHORT).show();
}else{
Log.d(TAG,
"name="+result.getName()+",address="
+result.getAddress()+",detail_url="
+result.getDetailUrl()+",shop_hours="
+result.getShopHours()+",telephone="
+result.getTelephone()+",price="
+result.getPrice()+",type="+result.getType()
+",tag="+result.getTag());
Toast.makeText(this,result.getName()+":"+result.getAddress(),
Toast.LENGTH_SHORT).show();
}
}

privateclassMyPoiOverlayextendsPoiOverlay{

publicMyPoiOverlay(BaiduMapbaiduMap){
super(baiduMap);
}

@Override
publicbooleanonPoiClick(intindex){
super.onPoiClick(index);
PoiInfopoi=getPoiResult().getAllPoi().get(index);
mPoiSearch.searchPoiDetail((newPoiDetailSearchOption()).poiUid(poi.uid));
returntrue;
}
}

测距、测面积

测量距离和测量面积是地图sdk的又一个应用,除了在地图上添加标注之外,就是要用到数学的两个公式。
其中测距用的是勾股定理(又名商高定理):勾股定理是一个基本的几何定理:一个直角三角形,两直角边的平方和等于斜边的平方。如果直角三角形两直角边为a和b,斜边为c,那么a*a+b*b=c*c
测面积用的是海伦公式(又名秦九韶公式):海伦公式是利用三角形的三个边长直接求三角形面积的公式,表达式为:S=&radic;p(p-a)(p-b)(p-c)。基于海伦公式,可以推导出根据多边形各边长求多边形面积的公式,即S = 0.5 * ( (x0*y1-x1*y0) + (x1*y2-x2*y1) + ... + (xn*y0-x0*yn) )


两种地图sdk在测量上的数学原理是一样的,只在添加地图标注上有些小差异,下面是使用高德地图进行测量的截图:
\


下面是两种地图sdk进行测量的代码例子:
百度地图
//下面是在地图上添加绘图操作
privatestaticintlineColor=0x55FF0000;
privatestaticintarcColor=0xbb00FFFF;
privatestaticinttextColor=0x990000FF;
privatestaticintpolygonColor=0x77FFFF00;
privatestaticintradius=100;
privateArrayListposArray=newArrayList();
booleanis_polygon=false;

privatevoidaddDot(LatLngpos){
if(is_polygon==true&&posArray.size()>1
&&MapUtil.isInsidePolygon(pos,posArray)==true){
Log.d(TAG,"isInsidePolygon");
LatLngcenterPos=MapUtil.getCenterPos(posArray);
OverlayOptionsooText=newTextOptions().bgColor(0x00ffffff)
.fontSize(26).fontColor(textColor).text("标题")//.rotate(-30)
.position(centerPos);
mMapLayer.addOverlay(ooText);
return;
}
if(is_polygon==true){
Log.d(TAG,"is_polygon==true");
posArray.clear();
is_polygon=false;
}
booleanis_first=false;
LatLngthisPos=pos;
if(posArray.size()>0){
LatLngfirstPos=posArray.get(0);
intdistance=(int)Math.round(MapUtil.getShortDistance(
thisPos.longitude,thisPos.latitude,firstPos.longitude,
firstPos.latitude));
//多次点击起点,要忽略之
if(posArray.size()==1&&distance<=0){
return;
}elseif(posArray.size()>1){
LatLnglastPos=posArray.get(posArray.size()-1);
intlastDistance=(int)Math.round(MapUtil.getShortDistance(
thisPos.longitude,thisPos.latitude,lastPos.longitude,
lastPos.latitude));
//重复响应当前位置的点击,要忽略之
if(lastDistance<=0){
return;
}
}
if(distance thisPos=firstPos;
is_first=true;
}
Log.d(TAG,"distance="+distance+",radius="+radius+",is_first="+is_first);

//画直线
LatLnglastPos=posArray.get(posArray.size()-1);
Listpoints=newArrayList();
points.add(lastPos);
points.add(thisPos);
OverlayOptionsooPolyline=newPolylineOptions().width(2)
.color(lineColor).points(points);
mMapLayer.addOverlay(ooPolyline);

//下面计算两点之间距离
distance=(int)Math.round(MapUtil.getShortDistance(
thisPos.longitude,thisPos.latitude,lastPos.longitude,
lastPos.latitude));
StringdisText="";
if(distance>1000){
disText=Math.round(distance*10/1000)/10d+"公里";
}else{
disText=distance+"米";
}
LatLngllText=newLatLng(
(thisPos.latitude+lastPos.latitude)/2,
(thisPos.longitude+lastPos.longitude)/2);
OverlayOptionsooText=newTextOptions().bgColor(0x00ffffff)
.fontSize(24).fontColor(textColor).text(disText)//.rotate(-30)
.position(llText);
mMapLayer.addOverlay(ooText);
}
if(is_first!=true){
//画圆圈
OverlayOptionsooCircle=newCircleOptions().fillColor(lineColor)
.center(thisPos).stroke(newStroke(2,0xAAFF0000)).radius(radius);
mMapLayer.addOverlay(ooCircle);
//画图片标记
BitmapDescriptorbitmapDesc=BitmapDescriptorFactory
.fromResource(R.drawable.icon_geo);
OverlayOptionsooMarker=newMarkerOptions().draggable(false)
.visible(true).icon(bitmapDesc).position(thisPos);
mMapLayer.addOverlay(ooMarker);
mMapLayer.setOnMarkerClickListener(newOnMarkerClickListener(){
@Override
publicbooleanonMarkerClick(Markermarker){
LatLngmarkPos=marker.getPosition();
addDot(markPos);
returntrue;
}
});
}else{
Log.d(TAG,"posArray.size()="+posArray.size());
//可能存在地图与标记同时响应点击事件的情况
if(posArray.size()<3){
posArray.clear();
is_polygon=false;
return;
}
//画多边形
OverlayOptionsooPolygon=newPolygonOptions().points(posArray)
.stroke(newStroke(1,0xFF00FF00))
.fillColor(polygonColor);
mMapLayer.addOverlay(ooPolygon);
is_polygon=true;

//下面计算多边形的面积
LatLngcenterPos=MapUtil.getCenterPos(posArray);
doublearea=Math.round(MapUtil.getArea(posArray));
StringareaText="";
if(area>1000000){
areaText=Math.round(area*100/1000000)/100d+"平方公里";
}else{
areaText=(int)area+"平方米";
}
OverlayOptionsooText=newTextOptions().bgColor(0x00ffffff)
.fontSize(26).fontColor(textColor).text(areaText)//.rotate(-30)
.position(centerPos);
mMapLayer.addOverlay(ooText);
}
posArray.add(thisPos);
if(posArray.size()>=3){
//画弧线
OverlayOptionsooArc=newArcOptions()
.color(arcColor)
.width(2)
.points(posArray.get(posArray.size()-1),
posArray.get(posArray.size()-2),
posArray.get(posArray.size()-3));
mMapLayer.addOverlay(ooArc);
}
}

@Override
publicvoidonMapClick(LatLngarg0){
addDot(arg0);
}

@Override
publicbooleanonMapPoiClick(MapPoiarg0){
addDot(arg0.getPosition());
returnfalse;
}


相关文章
最新文章
热点推荐