GIS內核-利用內核在Android上顯示瓦片數據集,並實現放大縮小

上一篇是基本顯示,不具備放大縮小能力,此篇實現了單機縮小,雙擊放大,實際功能代碼在200行左右

放大縮小原理爲:通過放大縮小改變視圖的分辨率,不同分辨率請求不同層級的瓦片,canvas繪製不同層級瓦片.

基本代碼如下:

package com.example.chijing.myapplication;

import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v7.widget.AppCompatImageView;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Matrix;
import com.geostar.kernel.*;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.widget.Toast;

import java.util.HashMap;
import java.util.Map;

import static android.content.ContentValues.TAG;
import static android.graphics.Bitmap.Config.ARGB_8888;
import static android.graphics.Paint.Style.STROKE;
import static android.graphics.Path.Direction.CCW;

public class MapView extends AppCompatImageView {

    GsDisplayTransformation m_DisplayTrans = null;
    GsTileClass m_Tcls = null;
    GsBox m_Box = new GsBox();
    GsSpatialReference m_Spatial = new GsSpatialReference(4326);
    GsPyramid m_Pyramid = new GsPyramid();

    HashMap<TileKey, GsTile> m_TileCache = null;
    int mParentWidth = 0, mParentHeight = 0;
    Bitmap m_Superbitmap = null;
    Canvas m_Cansvas = null;
    Paint m_Panit = null;



    void Init() {
        m_Panit = new Paint();
        m_Panit.setAntiAlias(true);
        setClickable(true);// 設置爲可點擊控件
        if (m_Tcls != null)
            return;
        m_TileCache = new HashMap<TileKey, GsTile>();
        GsConnectProperty conn = new GsConnectProperty();
        //conn.setServer("/mnt/sdcard/GeoGlobe/tmp/");
        conn.setServer("/mnt/sdcard/tmp/");
        GsESRIFileGeoDatabaseFactory pFac = new GsESRIFileGeoDatabaseFactory();

        GsGeoDatabase pDB = pFac.Open(conn);
        GsStringVector v = new GsStringVector();
        pDB.DataRoomNames(GsDataRoomType.eTileClass, v);
        m_Tcls = pDB.OpenTileClass("img.tpk");

        m_Box = m_Tcls.TileColumnInfo().getXYDomain();
        m_Spatial = m_Tcls.SpatialReference();
        String WKT = m_Spatial.ExportToWKT();
        m_Pyramid = m_Tcls.Pyramid();
        View mView = (View) getParent();
        ViewGroup mViewGroup = (ViewGroup) getParent();
        if (null != mViewGroup) {
            mParentWidth = mViewGroup.getWidth();
            mParentHeight = mViewGroup.getHeight();
        }
        double x2 = m_Box.getXMax();
        double xq= m_Box.getXMin();
        GsRect rc = new GsRect(0, 0, mParentWidth, mParentHeight);
        m_DisplayTrans = new GsDisplayTransformation(m_Box, rc);
         x2 = m_Box.getXMax();
         xq= m_Box.getXMin();
    }

    @Override
    protected void onDraw(Canvas canvas) {

        m_Cansvas = canvas;

        DrawTiles();
        DrawGrid();
        super.onDraw(canvas);
    }

    private void InitCache() {
        double res = m_DisplayTrans.Resolution();
        int nLevel = m_Pyramid.BestLevel(res);
        int[] range = new int[4];
        m_Pyramid.TileIndexRange(m_Box.getXMin(), m_Box.getYMin(), m_Box.getXMax(), m_Box.getYMax(), nLevel, range);
        GsTileCursor pCur = m_Tcls.Search(nLevel, range[0], range[1], range[2], range[3]);
        GsTile pTile = pCur.Next();
        int count = 0;

        do {
            if (GISHelp.IsEmptyTilePtr(pTile))
                break;
            count++;
            long l = pTile.Level();
            long r = pTile.Row();
            long c = pTile.Col();
            TileKey pkey = new TileKey(l, r, c);

            if (!m_TileCache.containsKey(pkey))
                m_TileCache.put(pkey, pTile);
            pTile = pCur.Next();

        } while (!GISHelp.IsEmptyTilePtr(pTile));

        //pCur.delete();
        //pCur = null;
        //System.gc();
        Log.i("tilescount", count + "");
    }

    public MapView(Context context) {
        super(context);
        Init();
        InitEvent();
    }


    public MapView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        Init();
        InitEvent();
    }

    public MapView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        Init();
        InitEvent();
    }

    protected void DrawTiles() {
        Log.d("DrawTile",""+1);
        ViewGroup mViewGroup = (ViewGroup) getParent();
        if (null != mViewGroup) {
            mParentWidth = mViewGroup.getWidth();
            mParentHeight = mViewGroup.getHeight();
        }
        GsRect rc = new GsRect(0, 0, mParentWidth, mParentHeight);
        if (m_DisplayTrans == null)
            m_DisplayTrans = new GsDisplayTransformation(m_Box, rc);
        double x2 = m_Box.getXMax();
        double xq= m_Box.getXMin();
        m_DisplayTrans.DeviceExtent(rc);
        m_DisplayTrans.MapExtent(m_Box);

        m_TileCache.clear();
        InitCache();


        Rect src = new Rect(0, 0, 256, 256);
        RectF dst = new RectF();
        double[] dblarray = new double[4];
        float[] fr = new float[4];

        for (Map.Entry<TileKey, GsTile> item : m_TileCache.entrySet()) {
            int l = item.getValue().Level();
            int r = item.getValue().Row();
            int c = item.getValue().Col();

            m_Pyramid.TileExtent(l, r, c, dblarray);

            m_DisplayTrans.FromMap(dblarray, 4, 2, fr);
            dst.left = fr[0];
            dst.top = fr[3];
            dst.right = fr[2];
            dst.bottom = fr[1];

            Bitmap bmp = GISHelp.Tile2Bitmap(item.getValue());
            m_Cansvas.drawBitmap(bmp, src, dst, m_Panit);

        }
        Log.d("DrawTile",""+2);
    }

    protected void DrawGrid() {
        Log.d("DraeGrid",""+2);
        m_Panit.setColor(Color.BLUE);
        m_Panit.setStyle(STROKE);//設置爲空填充,畫線

        GsRect rc = new GsRect(0, 0, mParentWidth, mParentHeight);
        double[] dblarray = new double[4];
        float[] fr = new float[4];
        RectF rf = new RectF();
        for (Map.Entry<TileKey, GsTile> item : m_TileCache.entrySet()) {
            int l = item.getValue().Level();
            int r = item.getValue().Row();
            int c = item.getValue().Col();

            m_Pyramid.TileExtent(l, r, c, dblarray);

            m_DisplayTrans.FromMap(dblarray, 4, 2, fr);
            rf.left = fr[0];
            rf.top = fr[3];
            rf.right = fr[2];
            rf.bottom = fr[1];
            Path path = new Path();
            path.addRect(rf, CCW);
            // float[] a= {rf.left,rf.bottom,rf.right,rf.bottom,rf.right,rf.top,rf.left,rf.top,rf.left,rf.bottom};
            m_Panit.setColor(Color.BLUE);
            m_Cansvas.drawPath(path, m_Panit);
            String str = "Level=" + l + "Row=" + r + "Col=" + c;
            m_Panit.setColor(Color.RED);
            m_Cansvas.drawText(str, rf.left, rf.bottom, m_Panit);
            item.getValue().delete();

        }

        Log.d("DraeGrid",""+3);
    }


    private GestureDetectorCompat m_GestureDetectorCompat = null;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return m_GestureDetectorCompat.onTouchEvent(event);
    }

    void InitEvent()
    {

        m_GestureDetectorCompat = new  GestureDetectorCompat( this.getContext(), new GestureListener());

        //setOnTouchListener(m_GestureDetectorCompat.);
        setFocusable(true);
        setClickable(true);
        setLongClickable(true);
    }

    private class GestureListener   implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener{
        public boolean onDown(MotionEvent e) {
            //showlog("onDown");
           // Toast.makeText(MainActivity.this, "onDown", Toast.LENGTH_SHORT).show();
return true;
        }

        public void onShowPress(MotionEvent e) {
            //showlog("onShowPress");
           // Toast.makeText(MainActivity.this, "onShowPress", Toast.LENGTH_SHORT).show();
        }

        public boolean onSingleTapUp(MotionEvent e) {
            if(m_DisplayTrans == null)
                return false;

            double f = m_DisplayTrans.Resolution()/3;
            if(f>0)
                m_DisplayTrans.Resolution(m_DisplayTrans.Resolution()+m_DisplayTrans.Resolution()/3);
            m_Box = m_DisplayTrans.MapExtent();
            invalidate();
            return true;
        }

        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {
            //showlog("onScroll:"+(e2.getX()-e1.getX()) +"   "+distanceX);
           // Toast.makeText(MainActivity.this, "onScroll", Toast.LENGTH_LONG).show();
            return true;
        }

        public void onLongPress(MotionEvent e) {
            //showlog("onLongPress");
            //Toast.makeText(MainActivity.this, "onLongPress", Toast.LENGTH_LONG).show();
        }

        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                               float velocityY) {
            //showlog("onFling");
            //Toast.makeText(MainActivity.this, "onFling", Toast.LENGTH_LONG).show();
            return true;
        }

        public boolean onSingleTapConfirmed(MotionEvent e) {
            //showlog("onSingleTapConfirmed");
            //Toast.makeText(MainActivity.this, "onSingleTapConfirmed",Toast.LENGTH_LONG).show();
            return true;
        }

        public boolean onDoubleTap(MotionEvent e) {
            //showlog("onDoubleTap");
            //Toast.makeText(MainActivity.this, "onDoubleTap", Toast.LENGTH_LONG).show();
            return true;
        }

        public boolean onDoubleTapEvent(MotionEvent e) {
            if(m_DisplayTrans == null)
                return false;

            double f = m_DisplayTrans.Resolution()/3;
            if(f>0)
                m_DisplayTrans.Resolution(m_DisplayTrans.Resolution()-m_DisplayTrans.Resolution()/3);
            m_Box = m_DisplayTrans.MapExtent();
            invalidate();
            return true;
        }
    };
}

 

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