入门Android开发----国家天地图开发= = 哈哈哈哈。。因为需要

来源:互联网 发布:怎样管理海量数据 编辑:程序博客网 时间:2024/05/23 21:13

http://api.tianditu.com/api-new/home.html

开发完回头修改了这个文章。

(有需求可参看《入门Android开发--ArcGis结合天地图实现地图建筑图层》)

天地图有国家和省的版本,地图显示详细度不一样(省的详细),功能不一样(国家的强)

所以根据需求,用了国家天地图(目前知道省的内部天地图Android客户端功能很强,但是没有sdk)

无需注册(百度地图说防止“balabla”,所以有个key),

在项目Libraries里添加tiandituapi2.2.2.jar,将libMapEngine.so复制到工程目录下的libs\armeabi下,再在android工程中引用jar和so文件

天地图里类参考中,mapview的一些类,在demo中有出现,但是说明里没有找着= =


//天地图常见的小问题就不多说了。可以百度类似的错误进行解决。

//大问题有:

//(路线规划的回调结果经常出错),一看错误类。。。-1为不支持的地图类型。。。呵呵

//  请看问题4


目前的需求和解决思路:

1、获取两个坐标点的“直线”距离,没有自带的方法。

答:网上找的(和百度地图的距离差不多吧):

double s =R*Math.acos(Math.cos(lat1*pi/180) *Math.cos(lat2*pi/180)*Math.cos(lng1*pi/180 -lng2*pi/180)+
Math.sin(lat1*pi/180 )*Math.sin(lat2*pi/180));

2、获取两个坐标点的路程距离。

答:用驾车规划里的回调结果,获取路程长度。或者使用网页服务

http://www.tianditu.cn/query.shtml   ,  POST方式:postStr={'orig':'120.957149,28.112149','dest':'120.957854,28.111113','style':'0','mid':''}&type=search

获取一个xml格式的结果

3、路线规划的结果需要恰好最合适显示在地图视图中间,

答:首先用自带的方法,确定返回结果的中心点,和视图的经纬度范围。

求经纬度范围有个自带的zoomToSpan方法,但是我这边的点位,起码试出了一个不能合理显示(有一个之后就没试其他的了)

然后就是自己写一个,这也是花了最多时间的部分。

思路大概就是先获取地图的缩放比例,经纬度范围(都是可以直接用的方法)

然后创建一个比例数组,和各个比例之间的比例尺的换算比例数组(如下代码块部分)

通过地图视图显示的经纬度乘以换算比例,和路线规划返回的经纬度点的经纬度范围进行比较,得到相应的缩放比例。

//缩放等级对应,如果地图未设置缩放等级,则为4km,即12。//minLevle为5,如果低于则设为5;maxLevel为18,如果高于则设为18//5为400km,6为200km,7为92km,8为48km,9为24km,(基本盖住温州了)//10为16km,11为8km,12为4km,13为2km,14为1km,15为500m,//16为240m,17为120m,18为60m,int[] level={5,6,7,8,9,10,11,12,13,14,15,16,17,18};double[] multiple={0.5,0.46,0.52,0.5,0.67,0.5,0.5,0.5,0.5,0.5,0.48,0.5,0.5};

4、如果有两个activity都使用了地图,两张地图会互相影响(包括地图图层的显示、比例和长宽)

答:目前没有好的办法,只能把第二张地图设置为第一张地图一样的设置。

5、结合3、4。因为我们先进入一个默认地图(全屏,假设100,map_def),然后点击目标点,

      进入路线规划,因为有其他面板,所以地图高度只用了部分(假设80, map_route)

      然后返回def的时候,def只会显示80的部分,下面20为空。

      如果route部分因为适应缩放改变了比例尺,那么def地图也会变化成相应的比例尺。

其实这个20,是通过动态计算的方法。(网上有计算组件高度的方法,但是我不知道怎么结合进这里,我用的是计算字符高度和空白高度的方法)

    为了说明方便,直接使用了20。

答:还不懂这个地图的原理,所以只好把route的地图也设置成100,不过20部分被面板遮盖。

然后在activity返回的时候设置route的缩放级别和def的一样(route通过intent获取def的缩放级别,在返回键和设置的back按钮点击事件中设置)

这样会有两个新的问题:地图的视图下移20/2(让画出来的线显示在下方的80中),经纬度范围为原纬度范围的4/5

这里下移20/2又需要换算成经纬度范围,(注意这里是比例尺改变之后的偏移,所以需要乘以不同的比例)

总结一下方法:计算比例尺等级的方法同3,然后通过比较旧的比例尺范围,还是3中的两个数组,进行比例换算,即可以算出新的比例尺下,20/2对应的纬度范围值

    通过将中心点的纬度坐标加上这个20/2对应的纬度范围值,即可完成中心点偏移操作。

6、在解决上面的问题的时候出现了地图无法缩放和移动的问题。

答:因为我把更改地图状态的函数写在了,overlay类里的重载draw方法中,

这个地图的机制大致是这样的:在更改地图图层状态的时候,通知所有的图层,调用draw方法,更改对应图层装态

(比如绘制路线的图层,就是在路线规划的回调中,将地图的中心点设置了一下之后,才调用了draw方法,开始绘制)

而产生这个问题的原因是,我把设置中心点放在了draw方法里,那每次拖动地图的时候,都会重新调用这个设置中心点的方法。

所以加了一个isFirstDraw的判断。即可解决。

7、代码怎么写呢。嘿嘿。主要的工具代码如下:(看不懂没事啊。不难,就是写了好久,放一下)

//缩放等级对应,如果地图未设置缩放等级,则为4km,即12。//minLevle为5,如果低于则设为5;maxLevel为18,如果高于则设为18//5为400km,6为200km,7为92km,8为48km,9为24km,(基本盖住温州了)//10为16km,11为8km,12为4km,13为2km,14为1km,15为500m,//16为240m,17为120m,18为60m,//在线路导航布局下,public class ZoomLevelUtil {//每次点击按钮的时候,比例等级都是不一定的。//所以需要判断int[] level={5,6,7,8,9,10,11,12,13,14,15,16,17,18};double[] multiple={0.5,0.46,0.52,0.5,0.67,0.5,0.5,0.5,0.5,0.5,0.48,0.5,0.5};GeoPoint point;Activity _activity;MapView mapView;int before_zoomLevel;//记录刚获取时视图的比例设置int after_zoomLevel;//记录最后确定的比例设置public ZoomLevelUtil(Activity activity,GeoPoint point,MapView mapView){this.point=point;_activity=activity;this.mapView=mapView;before_zoomLevel=mapView.getZoomLevel();//获取地图当前比例等级after_zoomLevel=mapView.getZoomLevel();}//解析进入时,每个地图视图被隐藏的高度(即上部面板高度对应的Lat值)public int parseSpan(int SpanE6){// TODO Auto-generated method stub//这个例子需要减去一部分,为22dp+4text+20sp DisplayMetrics metric = new DisplayMetrics();           _activity.getWindowManager().getDefaultDisplay().getMetrics(metric);           int height = metric.heightPixels; //屏幕高度         float scale=_activity.getResources().getDisplayMetrics().density;//屏幕密度           int title_height=DensityUtil.dip2px(_activity, 48);         height-=scale*title_height;                  //获取默认单个字符高度           TextPaint paint = new TextPaint();           FontMetrics fm = paint.getFontMetrics();           //Math.ceil(fm.descent - fm.top) + 2;         int deftext_Height=(int)Math.ceil(fm.descent - fm.ascent)  ;           //获取20sp字符单个高度         paint.setTextSize(20);         fm = paint.getFontMetrics();          int text_20_Height=(int)Math.ceil(fm.descent - fm.ascent) ;         int margin=DensityUtil.dip2px(_activity, 22);//上下总空余的距离22dp           return (int)(SpanE6*(scale*(double)(3*deftext_Height+text_20_Height+margin)/(double)height));         } //获取新的中心点坐标//需要先执行getAfterZoomLevel()public GeoPoint getFreshPoint(){int after_addLatSpan=0;//获取点击时,应该减小的距离int before_addLatSpan=parseSpan(mapView.getLatitudeSpan());//获取从before_zoomLevel转到after_zoomLevel,所需要的比例after_addLatSpan=(int)((double)before_addLatSpan*getScale(before_zoomLevel,after_zoomLevel));//要把地图往下移,其实是把中心点上调int after_LatSpan=point.getLatitudeE6()+after_addLatSpan/2;GeoPoint new_P=new GeoPoint(after_LatSpan,point.getLongitudeE6());//GeoPoint point = mResult.getCenterPoint();//int new_lat=point.getLatitudeE6()+addLngSpan/2;return new_P;}//计算,最终zoomLevel和传入的zoomLevel时,两者距离的比例//需要先执行getAfterZoomLevel()private double getScale(int before_zoomLevel,int after_zoomLevel) {// TODO Auto-generated method stubdouble scale=1;//获取处理前等级在列表中的位置int i=0;for(;i<level.length;i++){if(level[i]==before_zoomLevel){break;}}//获取处理后等级在列表中的位置int j=0;for(;j<level.length;j++){if(level[j]==after_zoomLevel){break;}}if(i<j){for(;i<j;i++)scale*=multiple[i];}else if(i>j){for(;i>j;){//i--;scale/=multiple[--i];}}return scale;}public int getAfterZoomLevel(int latSpanE6,int lngSpanE6){//int zoomLevel=15;//默认为15(15的比例比较适中,使用18或者12都有点不合适)int before_zoomLevel=mapView.getZoomLevel();int maxLevel=mapView.getMaxZoomLevel();int minLevel=mapView.getMinZoomLevel();//获取屏幕经纬度范围,int mapLatSpan=mapView.getLatitudeSpan();int mapLngSpan=mapView.getLongitudeSpan();//根据比例换算实际显示的高度mapLatSpan-=parseSpan(mapLatSpan);if(maxLevel!=18||minLevel!=5){Toast.makeText(_activity, "比例等级变化,校准失败", Toast.LENGTH_SHORT).show();return before_zoomLevel;}//获取等级在列表中的位置int i=0;for(;i<level.length;i++){if(level[i]==before_zoomLevel){break;}}//设置经度比例和纬度比例int latLevel=before_zoomLevel;int lngLevel=before_zoomLevel;int j=i;if(mapLatSpan<=latSpanE6){for(;mapLatSpan<=latSpanE6;){if(j==0)break;mapLatSpan/=multiple[j--];}}else{for(;mapLatSpan>latSpanE6;j++){if(j==(level.length-1))break;mapLatSpan*=multiple[j];}j--;}latLevel=level[j];j=i;if(mapLngSpan<=lngSpanE6){for(;mapLngSpan<=lngSpanE6;){if(j==0)break;j--;mapLngSpan/=multiple[j];}}else{for(;mapLngSpan>lngSpanE6;j++){if(j==(level.length-1))break;mapLngSpan*=multiple[j];}j--;}lngLevel=level[j];after_zoomLevel=latLevel<lngLevel?latLevel:lngLevel;return after_zoomLevel;}}



        

0 0