Android Open Source - android_maplib G I S Display






From Project

Back to project page android_maplib.

License

The source code is released under:

GNU General Public License

If you think the Android project android_maplib listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Project:  NextGIS Mobile/* ww  w  .  j av  a  2 s.c om*/
 * Purpose:  Mobile GIS for Android.
 * Author:   Dmitry Baryshnikov (aka Bishop), bishop.dev@gmail.com
 * *****************************************************************************
 * Copyright (c) 2012-2015. NextGIS, info@nextgis.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.nextgis.maplib.display;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.Log;
import com.nextgis.maplib.datasource.GeoEnvelope;
import com.nextgis.maplib.datasource.GeoPoint;

import static com.nextgis.maplib.util.Constants.*;
import static com.nextgis.maplib.util.GeoConstants.DEFAULT_MAX_ZOOM;
import static com.nextgis.maplib.util.GeoConstants.MERCATOR_MAX;


public class GISDisplay
{
    protected final Bitmap mBkBitmap;
    protected final int mTileSize = 256;
    protected final Paint       mRasterPaint;
    protected       Canvas      mMainCanvas;
    protected       Canvas      mBackgroundCanvas;
    protected       Bitmap      mMainBitmap;
    protected       Bitmap      mBackgroundBitmap;
    protected       GeoEnvelope mFullBounds;
    protected       GeoEnvelope mGeoLimits;
    protected       GeoEnvelope mCurrentBounds;
    protected       GeoPoint    mCenter;
    protected       GeoPoint    mMapTileSize;
    protected       Matrix      mTransformMatrix;
    protected       Matrix      mInvertTransformMatrix;
    protected       float       mMinZoomLevel;
    protected       float       mMaxZoomLevel;
    protected       float       mZoomLevel;
    protected       double      mScale;
    protected       double      mInvertScale;
    protected       float       mMainBitmapOffsetX;
    protected       float       mMainBitmapOffsetY;
    protected       GeoEnvelope mLimits;
    protected       GeoEnvelope mScreenBounds;
    protected       GeoEnvelope mOffScreenBounds;
    protected       int         mLimitType;


    public GISDisplay(Bitmap backgroundTile)
    {
        mBkBitmap = backgroundTile;
        //set max zoom
        mMinZoomLevel = 0;
        mMaxZoomLevel = DEFAULT_MAX_ZOOM;
        mLimitType = MAP_LIMITS_Y;

        mMainBitmap = null;
        mBackgroundBitmap = null;

        //default extent
        mFullBounds = new GeoEnvelope(-MERCATOR_MAX, MERCATOR_MAX, -MERCATOR_MAX,
                                      MERCATOR_MAX); //set full Mercator bounds
        mGeoLimits = mFullBounds;
        mCenter = mGeoLimits.getCenter();
        //default transform matrix
        mTransformMatrix = new Matrix();
        mInvertTransformMatrix = new Matrix();
        mMapTileSize = new GeoPoint();

        setSize(100, 100);

        mRasterPaint = new Paint();
        mRasterPaint.setAntiAlias(true);
        mRasterPaint.setFilterBitmap(true);
        mRasterPaint.setDither(true);
    }


    public void setSize(
            int w,
            int h)
    {
        Log.d(TAG, "new size: " + w + " x " + h);

        mScreenBounds = new GeoEnvelope(0, w, 0, h);
        double extraX = (w * OFFSCREEN_EXTRASIZE_RATIO - w) * .5;
        double extraY = (h * OFFSCREEN_EXTRASIZE_RATIO - h) * .5;
        mOffScreenBounds = new GeoEnvelope(-extraX, w + extraX, -extraY, h + extraY);

        // calc min zoom for no limits scenario
        // we calc the zoom level for full cover the whole display with tiles
        // if the zoom level is already set - do nothing
        float zoom = (float) Math.max(w, h) / mTileSize;
        mMinZoomLevel = (float) Math.ceil(Math.log(zoom) / Math.log(2.0));

        if(mMinZoomLevel < 0)
            mMinZoomLevel = 0;

        mBackgroundBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mBackgroundCanvas = new Canvas(mBackgroundBitmap);

        mMainBitmap = Bitmap.createBitmap((int) (w * OFFSCREEN_EXTRASIZE_RATIO),
                                          (int) (h * OFFSCREEN_EXTRASIZE_RATIO),
                                          Bitmap.Config.ARGB_8888);
        mMainCanvas = new Canvas(mMainBitmap);

        mMainBitmapOffsetX = (mMainBitmap.getWidth() - mBackgroundBitmap.getWidth()) * .5f;
        mMainBitmapOffsetY = (mMainBitmap.getHeight() - mBackgroundBitmap.getHeight()) * .5f;

        if (mZoomLevel < mMinZoomLevel) {
            mZoomLevel = mMinZoomLevel;
        }
        //default zoom and center
        setZoomAndCenter(mZoomLevel, mCenter);
    }


    public void setZoomAndCenter(
            float zoom,
            GeoPoint center)
    {
        if (zoom > mMaxZoomLevel || zoom < mMinZoomLevel) {
            return;
        }
        mZoomLevel = zoom;

        mCenter = center;
        if (mCenter.getX() > MERCATOR_MAX * 2) {
            mCenter.setX(mCenter.getX() - MERCATOR_MAX * 2);
        }

        int nZoom = (int) Math.floor(zoom);
        Log.d(TAG, "Zoom: " + zoom + ", Center: " + center.toString());

        double mapTileSize = 1 << nZoom;
        mapTileSize *= 1 + zoom - nZoom;
        double mapPixelSize = mapTileSize * mTileSize;

        mMapTileSize.setCoordinates(mFullBounds.width() / mapTileSize,
                                    mFullBounds.height() / mapTileSize);

        double scaleX = mapPixelSize / mFullBounds.width();
        double scaleY = mapPixelSize / mFullBounds.height();

        mScale = (float) ((scaleX + scaleY) * .5);
        mInvertScale = 1 / mScale;

        //default transform matrix
        mTransformMatrix.reset();
        mTransformMatrix.postTranslate((float) -center.getX(), (float) -center.getY());
        mTransformMatrix.postScale((float) mScale, (float) -mScale);
        mTransformMatrix.postTranslate((float) (mBackgroundBitmap.getWidth() * .5),
                                       (float) (mBackgroundBitmap.getHeight() * .5));

        mInvertTransformMatrix.reset();
        mTransformMatrix.invert(mInvertTransformMatrix);

        Matrix matrix = new Matrix();
        matrix.postTranslate((float) -center.getX(), (float) -center.getY());
        matrix.postScale((float) mScale, (float) -mScale);
        matrix.postTranslate((float) (mMainBitmap.getWidth() * .5),
                             (float) (mMainBitmap.getHeight() * .5));
        mMainCanvas.setMatrix(matrix);

        RectF rect =
                new RectF(-mMainBitmapOffsetX, mBackgroundBitmap.getHeight() + mMainBitmapOffsetY,
                          mBackgroundBitmap.getWidth() + mMainBitmapOffsetX, -mMainBitmapOffsetY);
        mInvertTransformMatrix.mapRect(rect);

//        mCurrentBounds = new GeoEnvelope(rect.left, rect.right, rect.bottom, rect.top);
        mCurrentBounds =
                new GeoEnvelope(Math.min(rect.left, rect.right), Math.max(rect.left, rect.right),
                                Math.min(rect.bottom, rect.top), Math.max(rect.bottom, rect.top));
        //Log.d(TAG, "current: " + mCurrentBounds.toString());

        mLimits = mapToScreen(mGeoLimits);
        mLimits.fix();
        if (mLimitType == MAP_LIMITS_X || mLimitType == MAP_LIMITS_NO) {
            mLimits.setMinY(mLimits.getMinY() - mMainBitmap.getHeight() * 2);
            mLimits.setMaxY(mLimits.getMaxY() + mMainBitmap.getHeight() * 2);
        }

        if (mLimitType == MAP_LIMITS_Y || mLimitType == MAP_LIMITS_NO) {
            mLimits.setMinX(mLimits.getMinX() - mMainBitmap.getWidth() * 2);
            mLimits.setMaxX(mLimits.getMaxX() + mMainBitmap.getWidth() * 2);
        }
    }


    public GeoEnvelope mapToScreen(final GeoEnvelope env)
    {
        GeoEnvelope outEnv = new GeoEnvelope();
        RectF rect = new RectF();
        rect.set((float) env.getMinX(), (float) env.getMaxY(), (float) env.getMaxX(),
                 (float) env.getMinY());

        mTransformMatrix.mapRect(rect);
        outEnv.setMin(rect.left, rect.bottom);
        outEnv.setMax(rect.right, rect.top);

        return outEnv;
    }

    /*public void setTransformMatrix(final double zoom, final GeoPoint center) {
        int nZoom = (int) Math.floor(zoom);

        double mapTileSize = 1 << nZoom;
        mapTileSize *= 1 + zoom - nZoom;
        double mapPixelSize = mapTileSize * mTileSize;

        double scaleX = mapPixelSize / mFullBounds.width();
        double scaleY = mapPixelSize / mFullBounds.height();
        double scale = (float) ((scaleX + scaleY) / 2.0);

        //default transform matrix
        mTransformMatrix.reset();
        mTransformMatrix.postTranslate((float) -center.getX(), (float) -center.getY());
        mTransformMatrix.postScale((float) scale, (float) -scale);
        mTransformMatrix.postTranslate(
                (float) mBackgroundBitmap.getWidth() / 2, (float) mBackgroundBitmap.getHeight() / 2);
    }*/


    public void clearLayer()
    {
        mMainBitmap.eraseColor(Color.TRANSPARENT);
    }


    public final GeoEnvelope getLimits()
    {
        return new GeoEnvelope(mLimits);
    }


    public final GeoEnvelope getScreenBounds()
    {
        return new GeoEnvelope(mScreenBounds);
    }


    public final GeoEnvelope getOffScreenBounds()
    {
        return new GeoEnvelope(mOffScreenBounds);
    }

    /*public synchronized Bitmap getEditDisplay() {
        return mBackgroundBitmap;
    }

    public synchronized Canvas getEditCanvas() {
        return mBackgroundCanvas;
    }*/


    public synchronized Bitmap getDisplay(boolean clearBackground)
    {
        return getDisplay(0, 0, clearBackground);
    }


    public synchronized Bitmap getDisplay(
            float x,
            float y,
            boolean clearBackground)
    {
        if (clearBackground) {
            clearBackground();
        }

        mBackgroundCanvas.drawBitmap(mMainBitmap, x - mMainBitmapOffsetX,
                                         y - mMainBitmapOffsetY, null);
        return mBackgroundBitmap;
    }


    public synchronized void clearBackground()
    {
        for (int i = 0; i < mBackgroundBitmap.getWidth(); i += mBkBitmap.getWidth()) {
            for (int j = 0; j < mBackgroundBitmap.getHeight(); j += mBkBitmap.getHeight()) {
                mBackgroundCanvas.drawBitmap(mBkBitmap, i, j, null);
            }
        }
    }


    public synchronized Bitmap getDisplay(
            float x,
            float y,
            float scale)
    {
        clearBackground();

        GeoPoint pt = getScaledOffset(x, y, scale);

        float mainBitmapOffsetX = (float) pt.getX();
        float mainBitmapOffsetY = (float) pt.getY();

        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);
        matrix.postTranslate(-mainBitmapOffsetX, -mainBitmapOffsetY);
        //Log.d(TAG, "matix: " + matrix.toShortString());

        synchronized (mMainBitmap) {
            mBackgroundCanvas.drawBitmap(mMainBitmap, matrix, mRasterPaint);
        }
        return mBackgroundBitmap;
    }


    public GeoPoint getScaledOffset(
            float x,
            float y,
            float scale)
    {
        float dxOld = x - mBackgroundBitmap.getWidth() / 2;
        float dyOld = y - mBackgroundBitmap.getHeight() / 2;

        float scaledWidth = mMainBitmap.getWidth() * scale;
        float scaledHeight = mMainBitmap.getHeight() * scale;

        GeoPoint ret = new GeoPoint();
        ret.setX((scaledWidth - mBackgroundBitmap.getWidth()) / 2 - (1 - scale) * dxOld);
        ret.setY((scaledHeight - mBackgroundBitmap.getHeight()) / 2 - (1 - scale) * dyOld);
        return ret;
    }


    public void drawTile(
            final Bitmap bitmap,
            final GeoPoint pt,
            Paint paint)
    {
        Matrix matrix = new Matrix();

        matrix.postScale((float) mInvertScale, (float) -mInvertScale);
        matrix.postTranslate((float) pt.getX(), (float) pt.getY());

        float scale = (float) (1 + mZoomLevel - Math.floor(mZoomLevel));

        if (bitmap.getWidth() != mTileSize) {
            scale = (float) mTileSize / bitmap.getWidth() * scale;
        }
        Matrix matrix1 = new Matrix();
        matrix1.postScale(scale, scale);
        matrix.preConcat(matrix1);

        synchronized (mMainBitmap) {
            if (paint == null) {
                mMainCanvas.drawBitmap(bitmap, matrix, mRasterPaint);
            } else {
                mMainCanvas.drawBitmap(bitmap, matrix, paint);
            }
        }
    }


    public void drawPoint(
            float x,
            float y,
            Paint paint)
    {
        mMainCanvas.drawPoint(x, y, paint);
    }


    public void drawLines(
            float[] pts,
            Paint paint)
    {
        mMainCanvas.drawLines(pts, paint);
    }


    public void drawCircle(
            float x,
            float y,
            float radius,
            Paint paint)
    {
        mMainCanvas.drawCircle(x, y, (float) (radius / mScale), paint);
    }


    public final double getScale()
    {
        return mScale;
    }


    public final GeoEnvelope getBounds()
    {
        return new GeoEnvelope(mCurrentBounds);
    }


    public final GeoEnvelope getFullBounds()
    {
        return new GeoEnvelope(mFullBounds);
    }


    public GeoPoint getTileSize()
    {
        return new GeoPoint(mMapTileSize);

        //RectF rect = new RectF(0, 0, mTileSize - 1, mTileSize - 1);
        //mInvertTransformMatrix.mapRect(rect);
        //return new double[] {rect.width(), rect.height()};
    }


    public GeoPoint screenToMap(final GeoPoint pt)
    {
        float points[] = new float[2];
        points[0] = (float) pt.getX();
        points[1] = (float) pt.getY();
        mInvertTransformMatrix.mapPoints(points);

        return new GeoPoint(points[0], points[1]);
    }


    public GeoPoint mapToScreen(final GeoPoint pt)
    {
        float points[] = new float[2];
        points[0] = (float) pt.getX();
        points[1] = (float) pt.getY();
        mTransformMatrix.mapPoints(points);

        return new GeoPoint(points[0], points[1]);
    }


    public GeoEnvelope screenToMap(final GeoEnvelope env)
    {
        GeoEnvelope outEnv = new GeoEnvelope();
        RectF rect = new RectF();
        rect.set((float) env.getMinX(), (float) env.getMaxY(), (float) env.getMaxX(),
                 (float) env.getMinY());

        mInvertTransformMatrix.mapRect(rect);
        outEnv.setMin(rect.left, rect.top); // screen axis Y and geo axis Y are inverse
        outEnv.setMax(rect.right, rect.bottom);


        return outEnv;
    }


    public float getMinZoomLevel()
    {
        return mMinZoomLevel;
    }


    public float getMaxZoomLevel()
    {
        return mMaxZoomLevel;
    }


    public GeoPoint getCenter()
    {
        return new GeoPoint(mCenter);
    }


    public void setGeoLimits(
            GeoEnvelope geoLimits,
            int limitType)
    {
        mGeoLimits = geoLimits;
        mLimitType = limitType;

        mLimits = mapToScreen(mGeoLimits);
        mLimits.fix();
        mLimits.adjust(mScreenBounds.width() / mScreenBounds.height());

        double scale = (float) (mScreenBounds.width()) / mLimits.width();
        double zoom = Math.log(scale) / Math.log(2.0);

        mMinZoomLevel = (float) Math.ceil(getZoomLevel() + zoom);
        mCenter = mGeoLimits.getCenter();
        setZoomAndCenter(mMinZoomLevel, mCenter);
        Log.d(TAG, "min zoom level: " + mMinZoomLevel + ", center:" + mCenter.toString());
    }


    public final float getZoomLevel()
    {
        return mZoomLevel;
    }


    public int getLimitType()
    {
        return mLimitType;
    }
}




Java Source Code List

com.nextgis.maplib.ApplicationTest.java
com.nextgis.maplib.api.GpsEventListener.java
com.nextgis.maplib.api.IGISApplication.java
com.nextgis.maplib.api.IJSONStore.java
com.nextgis.maplib.api.ILayerView.java
com.nextgis.maplib.api.ILayer.java
com.nextgis.maplib.api.IMapView.java
com.nextgis.maplib.api.INGWLayer.java
com.nextgis.maplib.api.IRenderer.java
com.nextgis.maplib.api.MapEventListener.java
com.nextgis.maplib.datasource.DatabaseHelper.java
com.nextgis.maplib.datasource.GeoEnvelope.java
com.nextgis.maplib.datasource.GeoGeometryCollection.java
com.nextgis.maplib.datasource.GeoGeometry.java
com.nextgis.maplib.datasource.GeoLineString.java
com.nextgis.maplib.datasource.GeoLinearRing.java
com.nextgis.maplib.datasource.GeoMultiLineString.java
com.nextgis.maplib.datasource.GeoMultiPoint.java
com.nextgis.maplib.datasource.GeoMultiPolygon.java
com.nextgis.maplib.datasource.GeoPoint.java
com.nextgis.maplib.datasource.GeoPolygon.java
com.nextgis.maplib.datasource.Geo.java
com.nextgis.maplib.datasource.NGWLayerContentProvider.java
com.nextgis.maplib.datasource.TileItem.java
com.nextgis.maplib.datasource.ngw.Connection.java
com.nextgis.maplib.datasource.ngw.Connections.java
com.nextgis.maplib.datasource.ngw.INGWResource.java
com.nextgis.maplib.datasource.ngw.LayerWithStyles.java
com.nextgis.maplib.datasource.ngw.ResourceGroup.java
com.nextgis.maplib.datasource.ngw.Resource.java
com.nextgis.maplib.display.GISDisplay.java
com.nextgis.maplib.display.Renderer.java
com.nextgis.maplib.display.SimpleFeatureRenderer.java
com.nextgis.maplib.display.SimpleLineStyle.java
com.nextgis.maplib.display.SimpleMarkerStyle.java
com.nextgis.maplib.display.Style.java
com.nextgis.maplib.display.TMSRenderer.java
com.nextgis.maplib.location.GpsEventSource.java
com.nextgis.maplib.map.LayerFactory.java
com.nextgis.maplib.map.LayerGroup.java
com.nextgis.maplib.map.Layer.java
com.nextgis.maplib.map.MapBase.java
com.nextgis.maplib.map.MapContentProviderHelper.java
com.nextgis.maplib.map.MapDrawable.java
com.nextgis.maplib.map.MapEventSource.java
com.nextgis.maplib.map.NGWRasterLayer.java
com.nextgis.maplib.map.NGWVectorLayer.java
com.nextgis.maplib.map.RemoteTMSLayer.java
com.nextgis.maplib.map.TMSLayer.java
com.nextgis.maplib.map.VectorLayer.java
com.nextgis.maplib.util.Constants.java
com.nextgis.maplib.util.DatabaseContext.java
com.nextgis.maplib.util.Feature.java
com.nextgis.maplib.util.FileUtil.java
com.nextgis.maplib.util.GeoConstants.java
com.nextgis.maplib.util.NetworkUtil.java
com.nextgis.maplib.util.SettingsConstants.java
com.nextgis.maplib.util.VectorCacheItem.java