ArcGis100.X版本 天地圖作爲底圖定位及定位圖標顯示問題

前面說過了加載天地圖,這篇文章是另一種加載方式:

  1. 頁面:
    <com.example.arcgisopen.uiview.SpotMapView
        android:id="@+id/smvMap"
        android:visibility="visible"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </com.example.arcgisopen.uiview.SpotMapView>

    2、 activity頁面;

    package com.example.arcgisopen.uiview;
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.util.AttributeSet;
    import android.widget.Toast;
    import com.example.arcgisopen.base.BaseApp;
    import com.esri.android.map.MapView;
    import com.esri.android.map.event.OnPinchListener;
    import com.esri.android.map.event.OnSingleTapListener;
    import com.esri.android.map.event.OnStatusChangedListener;
    import com.esri.android.map.event.OnZoomListener;
    public class SpotMapView extends MapView implements OnZoomListener,OnSingleTapListener,OnStatusChangedListener{
    private double[] mPresetScale = new double[]{2256.994353,4513.988705,9027.977411,18055.954822,36111.909643,72223.819286,144447.638572,288895.277144,577790.554289,1155581.108577,2311162.217155,4622324.434309,9244648.868618,1.8489297737236E7,3.6978595474472E7,7.3957190948944E7,1.47914381897889E8,2.95828763795777E8,5.91657527591555E8};
    //初始的比例尺
    private int mScaleLevel;
    //比例尺視圖
    private MapScaleView mScaleView;
    //指北針視圖
    private CompassView mCompassView;
    private SpotMapView.MapListener mMapListener;
    public void setMapListener(SpotMapView.MapListener listener){this.mMapListener = listener;}
    public interface MapListener{
        /**
         * 地圖加載完畢後的回調函數
         * */
        void onMapLoaded();
        /**
         * 地圖點擊回調
         * @param var1 屏幕x
         * @param var2 屏幕y
         */
        void onSingleTap(float var1, float var2);
        /**
         * 地圖縮放變化
         * @param scale 縮放
         */
        void scaleChanged(double scale);
    }
    @SuppressLint("ResourceType")
    public SpotMapView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOnZoomListener(this);
        setOnSingleTapListener(this);
        setOnStatusChangedListener(this);
    //        //地圖指北針事件
    //        setAllowRotationByPinch(true);
        setOnPinchListener(new OnPinchListener() {
            @Override
            public void prePointersMove(float v, float v1, float v2, float v3, double v4) {}
            @Override
            public void postPointersMove(float v, float v1, float v2, float v3, double v4) {
                float rotationAngle = Double.valueOf(getRotationAngle()).floatValue();
                mCompassView.updateDirection(-rotationAngle);
            }
            @Override
            public void prePointersDown(float v, float v1, float v2, float v3, double v4) {}
            @Override
            public void postPointersDown(float v, float v1, float v2, float v3, double v4) {}
            @Override
            public void prePointersUp(float v, float v1, float v2, float v3, double v4) {}
            @Override
            public void postPointersUp(float v, float v1, float v2, float v3, double v4) {}
        });
    }
    //縮放至大一個級別
    public void zoomUpper(){
        if (mScaleLevel<mPresetScale.length-2) {
            mScaleLevel++;
            setScaleLevel(mScaleLevel);
        }else {
            Toast.makeText(BaseApp.getContext(),"已縮放至最小級別!",Toast.LENGTH_LONG).show();
        }
    }
    //縮放至小一個級別
    public void zoomLower(){
        if (mScaleLevel>0) {
            mScaleLevel--;
            setScaleLevel(mScaleLevel);
        }else {
            Toast.makeText(BaseApp.getContext(),"已縮放至最大級別!",Toast.LENGTH_LONG).show();
        }
    }
    //設置縮放級別
    public void setScaleLevel(int level){
        if (level<0||level>=mPresetScale.length){
            return;
        }
        mScaleLevel = level;
        setScale(mPresetScale[level],true);
    }
    @Override
    public void setScale(double scale, boolean animated) {
        super.setScale(scale, animated);
        notifyScaleChanged();
    }
    //地圖縮放事件1
    @Override
    public void preAction(float v, float v1, double v2) {
    //        Log.d("數據測試","縮放開始");
    }
    //地圖縮放事件2
    @Override
    public void postAction(float v, float v1, double v2) {
        /**通知地圖的縮放改變了及時更新地圖的一些其他部件信息*/
        mScaleLevel = cacScaleLevel(getScale());
        notifyScaleChanged();
    }
    //比例尺顯示功能1
    public int cacScaleLevel(double curScale){
        int left = 0, right = mPresetScale.length-1,mid;
        while(left<right){
            mid = (right+left)/2;
            if (compare(mPresetScale[mid],curScale)==0){
                return mid;
            } else if (compare(mPresetScale[mid],curScale)>0){
                right = mid - 1;
            } else if (compare(mPresetScale[mid],curScale)<0){
                left = mid + 1;
            }
        }
        return left;
    }
    //比例尺顯示功能2
    private void notifyScaleChanged() {
        if (mScaleView!=null){
            mScaleView.refreshScaleView();
        }
        if (mMapListener!=null){
            mMapListener.scaleChanged(getScale());
        }
    //        Log.i("數據測試",mScaleLevel+"");
    }
    //比例尺顯示輔助函數
    private int compare(double d1, double d2){
        double accuracy = 0.001;
        if (d1-d2<0){
            return -1;
        }else if (d1-d2>accuracy){
            return 1;
        }else {
            return 0;
        }
    }
    //需在MainActivity中調用該方法給mScaleView賦值
    public void setScaleView(MapScaleView mScaleView) {
        mScaleView.setMapView(this);
        this.mScaleView = mScaleView;
    }
    //需在MainActivity中調用該方法給mCompassView賦值
    public void setCompassView(CompassView compassView) {
        this.mCompassView = compassView;
    }
    @Override
    public void onStatusChanged(Object o, STATUS status) {
        if (status.equals(STATUS.INITIALIZED)){
            mMapListener.onMapLoaded();
        }
    }
    @Override
    public void onSingleTap(float v, float v1) {
        if (mMapListener!=null){
            mMapListener.onSingleTap(v,v1);
        }
    }
    }

3、 天地圖文件TDTMapLayer

package com.example.arcgisopen.tianditu;
import com.esri.android.map.MapView;
public class TDTMapLayer {
    private static TDTTiledMapServiceLayer t_vec=new TDTTiledMapServiceLayer(TDTTiledMapServiceType.VEC_C);
    private static TDTTiledMapServiceLayer t_cva=new TDTTiledMapServiceLayer(TDTTiledMapServiceType.CVA_C);
    private static TDTTiledMapServiceLayer t_img= new TDTTiledMapServiceLayer(TDTTiledMapServiceType.IMG_C);
    private static TDTTiledMapServiceLayer t_cia= new TDTTiledMapServiceLayer(TDTTiledMapServiceType.CIA_C);
    private static boolean Layervisible=true;
    public static boolean isLayervisible() {
        return Layervisible;
    }
    public static void addToMap(MapView map){
        t_vec=new TDTTiledMapServiceLayer(TDTTiledMapServiceType.VEC_C);
        t_cva=new TDTTiledMapServiceLayer(TDTTiledMapServiceType.CVA_C);
        t_img= new TDTTiledMapServiceLayer(TDTTiledMapServiceType.IMG_C);
        t_cia= new TDTTiledMapServiceLayer(TDTTiledMapServiceType.CIA_C);
        map.addLayer(t_vec);
        map.addLayer(t_cva);
        map.addLayer(t_img);
        map.addLayer(t_cia);
        setTDTMapLayerVisible(Layervisible);
    }
    public static void changeTDTMapLayerVisible(){
        Layervisible = !Layervisible;
        if(Layervisible==false){
            t_img.setVisible(true);
            t_cia.setVisible(true);
            t_cva.setVisible(false);
            t_vec.setVisible(false);
        }else {
            t_img.setVisible(false);
            t_cia.setVisible(false);
            t_cva.setVisible(true);
            t_vec.setVisible(true);
        }
    }
    public static void setTDTMapLayerVisible(Boolean isvisible){
        Layervisible = isvisible;
        if(isvisible==false){
            t_img.setVisible(true);
            t_cia.setVisible(true);
            t_cva.setVisible(false);
            t_vec.setVisible(false);
        }else{
            t_img.setVisible(false);
            t_cia.setVisible(false);
            t_cva.setVisible(true);
            t_vec.setVisible(true);
        }
    }
}

4、天地圖文件二:TDTTiledMapServiceLayer

package com.example.arcgisopen.tianditu;

import android.util.Log;

import com.esri.android.map.TiledServiceLayer;
import com.esri.core.geometry.Envelope;
import com.esri.core.geometry.Point;
import com.esri.core.geometry.SpatialReference;
import com.esri.core.io.UserCredentials;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.RejectedExecutionException;

public class TDTTiledMapServiceLayer extends TiledServiceLayer {
    private TDTTiledMapServiceType _mapType;
    private TileInfo tiandituTileInfo;

    public TDTTiledMapServiceLayer() {
        this(null, null, true);
    }

    public TDTTiledMapServiceLayer(TDTTiledMapServiceType mapType) {
        this(mapType, null, true);
    }

    public TDTTiledMapServiceLayer(TDTTiledMapServiceType mapType, UserCredentials usercredentials) {
        this(mapType, usercredentials, true);
    }

    public TDTTiledMapServiceLayer(TDTTiledMapServiceType mapType, UserCredentials usercredentials, boolean flag) {
        super("");
        this._mapType = mapType;
        setCredentials(usercredentials);

        if (flag)
            try {
                getServiceExecutor().submit(new Runnable() {

                    public final void run() {
                        a.initLayer();
                    }

                    final TDTTiledMapServiceLayer a;

                    {
                        a = TDTTiledMapServiceLayer.this;
                    }
                });
                return;
            } catch (RejectedExecutionException _ex) {
            }
    }

    public TDTTiledMapServiceType getMapType() {
        return this._mapType;
    }

    protected void initLayer() {
        this.buildTileInfo();
        this.setFullExtent(new Envelope(103.36, 24.37, 109.35, 29.13));
        this.setDefaultSpatialReference(SpatialReference.create(4490));   //CGCS2000
//        //this.setDefaultSpatialReference(SpatialReference.create(4326));
//        //this.setInitialExtent(new Envelope(115.40,39.33,117.50,41.10));
        this.setInitialExtent(new Envelope(103.36, 24.37, 109.35, 29.13));
        super.initLayer();
    }

    public void refresh() {
        try {
            getServiceExecutor().submit(new Runnable() {

                public final void run() {
                    if (a.isInitialized())
                        try {
                            a.b();
                            a.clearTiles();
                            return;
                        } catch (Exception exception) {
                            Log.e("ArcGIS", "Re-initialization of the layer failed.", exception);
                        }
                }

                final TDTTiledMapServiceLayer a;

                {
                    a = TDTTiledMapServiceLayer.this;
                    //super();
                }
            });
            return;
        } catch (RejectedExecutionException _ex) {
            return;
        }
    }

    final void b() throws Exception {

    }

    @Override
    protected byte[] getTile(int level, int col, int row) throws Exception {

        byte[] result = null;
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            URL sjwurl = new URL(this.getTianDiMapUrl(level, col, row));
            HttpURLConnection httpUrl = null;
            BufferedInputStream bis = null;
            byte[] buf = new byte[1024];

            httpUrl = (HttpURLConnection) sjwurl.openConnection();
            httpUrl.connect();
            bis = new BufferedInputStream(httpUrl.getInputStream());

            while (true) {
                int bytes_read = bis.read(buf);
                if (bytes_read > 0) {
                    bos.write(buf, 0, bytes_read);
                } else {
                    break;
                }
            }
            bis.close();
            httpUrl.disconnect();
            result = bos.toByteArray();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return result;
    }

    @Override
    public TileInfo getTileInfo() {
        return this.tiandituTileInfo;
    }

    private String getTianDiMapUrl(int level, int col, int row) {
        String url = new TDTUrl(level, col, row, this._mapType).generatUrl();
        return url;
    }

    private void buildTileInfo() {
        Point originalPoint = new Point(-180, 90);
        double[] res = {
                1.40625,
                0.703125,
                0.3515625,
                0.17578125,
                0.087890625,
                0.0439453125,
                0.02197265625,
                0.010986328125,
                0.0054931640625,
                0.00274658203125,
                0.001373291015625,
                0.0006866455078125,
                0.00034332275390625,
                0.000171661376953125,
                8.58306884765629E-05,
                4.29153442382814E-05,
                2.14576721191407E-05,
                1.07288360595703E-05,
                5.36441802978515E-06,
                2.68220901489258E-06,
                1.34110450744629E-06
        };
        double[] scale = {
                400000000,
                295497598.5708346,
                147748799.285417,
                73874399.6427087,
                36937199.8213544,
                18468599.9106772,
                9234299.95533859,
                4617149.97766929,
                2308574.98883465,
                1154287.49441732,
                577143.747208662,
                288571.873604331,
                144285.936802165,
                72142.9684010827,
                36071.4842005414,
                18035.7421002707,
                9017.87105013534,
                4508.93552506767,
                2254.467762533835,
                1127.2338812669175,
                563.616940
        };
        int levels = 19;
        int dpi = 96;
        int tileWidth = 256;
        int tileHeight = 256;
        this.tiandituTileInfo = new TileInfo(originalPoint, scale, res, levels, dpi, tileWidth, tileHeight);
        this.setTileInfo(this.tiandituTileInfo);
    }
}

5、天地圖文件三:TDTTiledMapServiceType

package com.example.arcgisopen.tianditu;

public enum TDTTiledMapServiceType {
    /**
     * 天地圖矢量
     * */
    VEC_C,
    /**
     * 天地圖影像
     * */
    IMG_C,
    /**
     * 天地圖矢量標註
     * */
    CVA_C,
    /**
     * 天地圖影像標註
     * */
    CIA_C
}

6、天地圖文件四:TDTUrl

package com.example.arcgisopen.tianditu;

import java.util.Random;

/**
 * Created by Fly on 2016/9/6.
 */
public class TDTUrl {
    private TDTTiledMapServiceType _tiandituMapServiceType;
    private int _level;
    private int _col;
    private int _row;
    public TDTUrl(int level, int col, int row,TDTTiledMapServiceType tiandituMapServiceType){
        this._level=level;
        this._col=col;
        this._row=row;
        this._tiandituMapServiceType=tiandituMapServiceType;
    }
    public String generatUrl(){
        /**
         * 天地圖矢量、影像
         * */
        StringBuilder url=new StringBuilder("http://t");
        Random random=new Random();
        int subdomain = (random.nextInt(6) + 1);
        url.append(subdomain);
        switch(this._tiandituMapServiceType){
            case VEC_C:
                url.append(".tianditu.com/DataServer?T=vec_c&X=").append(this._col).append("&Y=").append(this._row).append("&L=").append(this._level).append("&tk=a4edecc3a1040656f20e39976c1f357b");;
                break;
            case CVA_C:
                url.append(".tianditu.com/DataServer?T=cva_c&X=").append(this._col).append("&Y=").append(this._row).append("&L=").append(this._level).append("&tk=a4edecc3a1040656f20e39976c1f357b");;
                break;
            case CIA_C:
                url.append(".tianditu.com/DataServer?T=cia_c&X=").append(this._col).append("&Y=").append(this._row).append("&L=").append(this._level).append("&tk=a4edecc3a1040656f20e39976c1f357b");;
                break;
            case IMG_C:
                url.append(".tianditu.com/DataServer?T=img_c&X=").append(this._col).append("&Y=").append(this._row).append("&L=").append(this._level).append("&tk=a4edecc3a1040656f20e39976c1f357b");;
                break;
            default:
                return null;
        }
        return url.toString();
    }
}

7、MainActivity.class
1、

    @BindView(R.id.smvMap)
            SpotMapView mMapView;
2、TDTMapLayer.addToMap(mMapView);在初始化的時候加載天地圖

3、定位:定位通過Location獲取當經度緯度就可以了,不需要轉換,直接用,百度上還是很多的,這裏就不介紹怎麼去獲取了。
 Point p = new Point(經度, 緯度);
    mMapView.zoomToScale(p, 9000);
```
4、顯示定位圖標,在activity,ocreate()中使用或初始化activity的時候使用此方法就可以了。
private void position() {
    LocationDisplayManager ldm = mMapView.getLocationDisplayManager();

    ldm.setLocationListener(new LocationListener() {
        boolean locationChanged = false;

        @Override

        public void onStatusChanged(String provider, int status, Bundle extras) {
        }

        //GPS開啓時觸發

        @Override

        public void onProviderEnabled(String provider) {
        // TODO Auto-generated method stub

        }

        @Override

        public void onProviderDisabled(String provider) {
        // TODO Auto-generated method stub

        }

        @Override

        public void onLocationChanged(Location location) {

// TODO Auto-generated method stub

            if (!locationChanged) {
                locationChanged = true;

            }

        }

    });
    ldm.start();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章