From 7e65219d9d073cbcc735d1119290707953aede29 Mon Sep 17 00:00:00 2001 From: jventribout Date: Mon, 7 Jan 2013 17:46:07 +0100 Subject: [PATCH] Dual grid Pinch to zoom OK Tile display order on refresh sorted DEV MODE --- res/values/strings.xml | 8 +- .../hexagon/map/HexagonMapApplication.java | 4 +- src/com/hexagon/map/Image.java | 36 ++- src/com/hexagon/map/MapActivity.java | 82 +++++-- src/com/hexagon/map/Tile.java | 110 +++++---- src/com/hexagon/map/Viewport.java | 221 ++++++++++++++---- .../download/CacheBitmapDownloadService.java | 7 +- .../download/HttpBitmapDownloadService.java | 15 +- 8 files changed, 364 insertions(+), 119 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 33bad04..b18f9f6 100755 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2,8 +2,12 @@ HexagonMap Search - http://gpp3-wxs.ign.fr/4l9i6682teki4ang459b653o/geoportail/wmts?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=GEOGRAPHICALGRIDSYSTEMS.MAPS&STYLE=normal&FORMAT=image/jpeg&TILEMATRIXSET=PM&TILEMATRIX=!SCALE!&TILEROW=!ROW!&TILECOL=!COL! - http://gpp3-wxs.ign.fr/4l9i6682teki4ang459b653o/geoportail/ols? + + http://gpp3-wxs.ign.fr/czj03g5y31qfnzwu782qd79t/geoportail/wmts?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=GEOGRAPHICALGRIDSYSTEMS.MAPS&STYLE=normal&FORMAT=image/jpeg&TILEMATRIXSET=PM&TILEMATRIX=!SCALE!&TILEROW=!ROW!&TILECOL=!COL! + http://gpp3-wxs.ign.fr/czj03g5y31qfnzwu782qd79t/geoportail/ols? + + + Conditions générales d’utilisation finale, API Géoportail OK Je refuse diff --git a/src/com/hexagon/map/HexagonMapApplication.java b/src/com/hexagon/map/HexagonMapApplication.java index ed198d4..f94582e 100644 --- a/src/com/hexagon/map/HexagonMapApplication.java +++ b/src/com/hexagon/map/HexagonMapApplication.java @@ -6,13 +6,13 @@ import android.app.Application; -@ReportsCrashes(formKey = "dHR0SUQ4WDEwekpVbHMwOHhGT3ZQeHc6MQ", mode=ReportingInteractionMode.TOAST) +//@ReportsCrashes(formKey = "dHR0SUQ4WDEwekpVbHMwOHhGT3ZQeHc6MQ", mode=ReportingInteractionMode.TOAST) public class HexagonMapApplication extends Application { @Override public void onCreate() { super.onCreate(); // The following line triggers the initialization of ACRA - ACRA.init(this); +// ACRA.init(this); } } diff --git a/src/com/hexagon/map/Image.java b/src/com/hexagon/map/Image.java index 0931cda..d379d50 100755 --- a/src/com/hexagon/map/Image.java +++ b/src/com/hexagon/map/Image.java @@ -10,29 +10,37 @@ import com.hexagon.map.preference.Preferences; import com.hexagon.map.util.JveLog; -public class Image { +public class Image implements Cloneable { public volatile LoadState state = LoadState.LOADING; public volatile HttpGet method; - private String src; + private volatile String src; - private String cacheFileName; + private volatile String cacheFileName; public Bitmap bmp; public int alpha = 255; + public boolean visibleOnTop = true; + +// public boolean visibleOnTop = false; + public Image(String src, String cacheFileName) { update(src, cacheFileName); } - public void update(String src, String cacheFileName) { + public Image() { + // TODO Auto-generated constructor stub + } + + public synchronized void update(String src, String cacheFileName) { this.src = src; this.cacheFileName = cacheFileName; - state = LoadState.LOADING; startLoadBitmap(); + alpha = 0; } public void setSrc(String src) { @@ -49,11 +57,14 @@ private void startLoadBitmap() { .getBitmapFromMemCache(cacheFileName); if (bitmapFromMemCache != null) { bmp = bitmapFromMemCache; + state = LoadState.LOADED; + visibleOnTop = true; JveLog.d("Image", "Loaded from LRU Cache"); return; } } // JveLog.d("Image", "NOT Loaded from LRU Cache"); + state = LoadState.LOADING; CacheBitmapDownloadService.getInstance().submit(this); } @@ -87,5 +98,20 @@ public void clear() { public boolean isCleared() { return (state == LoadState.CLEARED); } + + @Override + protected Image clone() throws CloneNotSupportedException { + Image clone = (Image) super.clone(); + if (bmp != null) { +// clone.bmp = Bitmap.createBitmap(bmp); + clone.bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth()/2, bmp.getHeight(), null, true); + clone.bmp = bmp.copy(bmp.getConfig(), false); + } + return clone; + } + + public boolean isLoaded() { + return (state == LoadState.LOADED); + } } diff --git a/src/com/hexagon/map/MapActivity.java b/src/com/hexagon/map/MapActivity.java index b2e5f7d..87715b5 100755 --- a/src/com/hexagon/map/MapActivity.java +++ b/src/com/hexagon/map/MapActivity.java @@ -74,6 +74,7 @@ public class MapActivity extends SherlockActivity implements OnGestureListener, private Sensor mSensor; private ImageButton fsLocationButton; private Date stopTime; + public long pinchDoneTime; // ///////////////////////////////////////////////////////////////// // Lifecycle @@ -131,7 +132,6 @@ protected void onStart() { mScaleDetector = new ScaleGestureDetector(this, new GestureListenerFactory() .getGestureListener(rescalePinchZoom)); - clearTimedCache(); } @@ -321,7 +321,6 @@ private void initDisplay() { main = new MapView(this, this); - setContentView(R.layout.main); LinearLayout content = (LinearLayout) findViewById(R.id.mapLayout); @@ -335,7 +334,11 @@ private void initDisplay() { handleFullScreen(Preferences.isFullScreen()); - + initZoomController(); + + } + + private void initZoomController() { controller = new ZoomButtonsController(main); controller.setOnZoomListener(new OnZoomListener() { @@ -351,9 +354,8 @@ public void onVisibilityChanged(boolean visible) { controller.setVisible(visible); } }); -// controller.setVisible(true); + // controller.setVisible(true); controller.setAutoDismissed(true); - } /** @@ -394,7 +396,7 @@ public boolean onSingleTapConfirmed(MotionEvent e) { } private void zoomIn() { - if (!viewport.isZoomMax()) { + if (!viewport.isZoomMax() && !viewport.zoomOnGoing) { JveLog.d(TAG, "zoom in"); JveLog.d(TAG, "scale : " + viewport.scale); viewport.zoomInAnimated(); @@ -403,18 +405,20 @@ private void zoomIn() { } private void zoomOut() { - JveLog.d(TAG, "zoom out"); - JveLog.d(TAG, "scale : " + viewport.scale); - viewport.zoomOutAnimated(); - handleZoomControl(); + if (!viewport.isZoomMin() && !viewport.zoomOnGoing) { + JveLog.d(TAG, "zoom out"); + JveLog.d(TAG, "scale : " + viewport.scale); + viewport.zoomOutAnimated(); + handleZoomControl(); + } } private void zoom(int zoomOffset) { if (zoomOffset > 0 && !viewport.isZoomMax()) { - viewport.scale += zoomOffset; + viewport.zoomAnimated(zoomOffset); } if (zoomOffset < 0 && !viewport.isZoomMin()) { - viewport.scale += zoomOffset; + viewport.zoomAnimated(zoomOffset); } handleZoomControl(); } @@ -539,6 +543,19 @@ protected void onSaveInstanceState(Bundle outState) { @Override public boolean onTouchEvent(MotionEvent me) { + // long timeSincePinch = System.currentTimeMillis() - pinchDoneTime; + // if (timeSincePinch < 4) { + // return false; + // } + // + // if (me.getAction() == MotionEvent.ACTION_POINTER_UP + // || me.getAction() == MotionEvent.ACTION_UP) { + // pinchDone = false; + // } + // mScaleDetector.onTouchEvent(me); + // if (pinchDone) { + // return true; + // } mScaleDetector.onTouchEvent(me); viewport.resetInertiaScroll(); @@ -658,6 +675,7 @@ public boolean onOptionsItemSelected( private void handleFullScreen(boolean fullScreen) { if (fullScreen) { getSupportActionBar().hide(); + } else { getSupportActionBar().show(); } @@ -668,6 +686,7 @@ private void handleFullScreen(boolean fullScreen) { locationButton.setVisibility(fullScreen ? View.VISIBLE : View.GONE); ImageButton fsOffButton = (ImageButton) findViewById(R.id.fsOffButton); fsOffButton.setVisibility(fullScreen ? View.VISIBLE : View.GONE); + initZoomController(); } // ///////////////////////////////////////////////////////////////// @@ -731,6 +750,7 @@ public void onScaleEnd(ScaleGestureDetector detector) { @Override public boolean onScaleBegin(ScaleGestureDetector detector) { + viewport.copyGrid(); initialScaleFactor = 1.0f; return true; } @@ -758,40 +778,58 @@ public boolean onScale(ScaleGestureDetector detector) { public class TouchUpReScaleGestureListener implements OnScaleGestureListener { + private static final float ZOOM_OUT_THESHOLD = 0.5f; + private static final float ZOOM_IN_THESHOLD = 2.0f; + @Override public void onScaleEnd(ScaleGestureDetector detector) { int zoomOffset = Math.round(viewport.zoomScale) - 1; + Log.d(TAG, "zoom offset : " + zoomOffset); + + if (zoomOffset > 1) + zoomOffset = 1; + if (zoomOffset < -1) + zoomOffset = -1; zoom(zoomOffset); if (zoomOffset == 0) { viewport.zoomReset(null); } float oldScale = viewport.zoomScale; - if (viewport.zoomScale < 0.5f) { - oldScale = viewport.zoomScale * 2; - - } else if (viewport.zoomScale < 2.0f) { - oldScale = viewport.zoomScale / 2; - } + // if (viewport.zoomScale < ZOOM_OUT_THESHOLD) { + // oldScale = ZOOM_OUT_THESHOLD; + // + // } else if (viewport.zoomScale > ZOOM_IN_THESHOLD) { + // oldScale = ZOOM_IN_THESHOLD; + // } viewport.zoomScale = 1.0f; - viewport.refresh(); + // viewport.refresh(); if (zoomOffset != 0) { viewport.zoomReset(oldScale); } pinchDone = true; + pinchDoneTime = System.currentTimeMillis(); } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { + if (viewport.zoomOnGoing) { + return true; + } + viewport.copyGrid(); return true; } @Override public boolean onScale(ScaleGestureDetector detector) { - Log.d(TAG, "zoom ongoing, scale: " + detector.getScaleFactor()); - viewport.zoomScale = detector.getScaleFactor(); + if (!viewport.zoomOnGoing) { + return true; + } + + JveLog.d(TAG, "zoom ongoing, scale: " + detector.getScaleFactor()); + viewport.zoomScale *= detector.getScaleFactor(); pinchDone = true; - return false; + return true; } } diff --git a/src/com/hexagon/map/Tile.java b/src/com/hexagon/map/Tile.java index 5cbddff..0804167 100755 --- a/src/com/hexagon/map/Tile.java +++ b/src/com/hexagon/map/Tile.java @@ -8,14 +8,17 @@ import android.graphics.Matrix; import android.graphics.Paint; import android.os.Handler; +import android.util.Log; +import com.hexagon.map.enums.LoadState; import com.hexagon.map.geo.AbstractPositionableElement; import com.hexagon.map.preference.Preferences; import com.hexagon.map.util.JveLog; -public class Tile extends AbstractPositionableElement { +public class Tile extends AbstractPositionableElement implements Cloneable { -// private static final String URL = "http://gpp3-wxs.ign.fr/czj03g5y31qfnzwu782qd79t/geoportail/wmts?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=GEOGRAPHICALGRIDSYSTEMS.MAPS&STYLE=normal&FORMAT=image/jpeg&TILEMATRIXSET=PM&TILEMATRIX=!SCALE!&TILEROW=!ROW!&TILECOL=!COL!"; + // private static final String URL = + // "http://gpp3-wxs.ign.fr/czj03g5y31qfnzwu782qd79t/geoportail/wmts?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=GEOGRAPHICALGRIDSYSTEMS.MAPS&STYLE=normal&FORMAT=image/jpeg&TILEMATRIXSET=PM&TILEMATRIX=!SCALE!&TILEROW=!ROW!&TILECOL=!COL!"; private static final String TAG = "Tile"; @@ -26,18 +29,20 @@ public class Tile extends AbstractPositionableElement { public boolean visible = true; - private final Viewport layer; + private final Viewport viewport; final Handler initGeoCookieHandler = new Handler(); protected boolean threadRunning = Preferences.threadPool; - private Image image; + Image image = new Image(); private Matrix m = new Matrix(); + // public AbstractPositionableElement position = new Point(); + public Tile(Viewport layer, int ix, int iy) { - this.layer = layer; + this.viewport = layer; indexX = ix; indexY = iy; } @@ -46,36 +51,35 @@ public void draw(Canvas canvas, int scrollX, int scrollY, Paint paint) { int x = posx; int y = posy; if (visible && Preferences.drawMap) { - if (image != null && image.bmp != null) { + if (image != null && image.bmp != null && image.isLoaded()) { canvas.drawBitmap(image.bmp, x, y, paint); } else { - canvas.drawBitmap(layer.noSrcBmp, x, y, paint); + canvas.drawBitmap(viewport.noSrcBmp, x, y, paint); } } if (Preferences.isDrawInfos()) { drawDebugInfos(canvas, paint, x, y); } - - - + List l = new ArrayList(); l.add("test"); } - public void draw(Canvas canvas, Matrix scaleM, Paint paint) { int x = posx; int y = posy; if (visible && Preferences.drawMap) { - m = new Matrix(scaleM); + m = new Matrix(scaleM); m.preTranslate(posx, posy); - if (image != null && image.bmp != null && m != null) { + if (image != null && image.bmp != null && m != null + && image.isLoaded()) { if (image.alpha < 255) { Paint paintAlpha = new Paint(paint); - canvas.drawBitmap(layer.noSrcBmp, m, paint); + // canvas.drawBitmap(layer.noSrcBmp, m, paint); image.alpha = image.alpha + 20; - if (image.alpha > 255) image.alpha = 255; + if (image.alpha > 255) + image.alpha = 255; paintAlpha.setAlpha(image.alpha); canvas.drawBitmap(image.bmp, m, paintAlpha); } else { @@ -83,9 +87,9 @@ public void draw(Canvas canvas, Matrix scaleM, Paint paint) { canvas.drawBitmap(image.bmp, m, paint); } } else { - canvas.drawBitmap(layer.noSrcBmp, m, paint); -// BitmapDrawable bd = new BitmapDrawable(layer.noSrcBmp); -// bd.draw(canvas); + canvas.drawBitmap(viewport.noSrcBmp, m, paint); + // BitmapDrawable bd = new BitmapDrawable(layer.noSrcBmp); + // bd.draw(canvas); } } if (Preferences.isDrawInfos()) { @@ -110,7 +114,7 @@ private void drawDebugInfos(Canvas canvas, Paint paint, int x, int y) { canvas.drawText("TileX : " + mapTileX + "/ TileY : " + mapTileY, x, y + 40, paint); canvas.drawText("x : " + x + "/ y: " + y, x, y + 60, paint); - canvas.drawText("visible : " + visible , x, y + 80, paint); + canvas.drawText("visible : " + visible, x, y + 80, paint); if (image != null && image.getCacheFileName() != null) { canvas.drawText(image.getCacheFileName(), x, y + 100, paint); } @@ -124,25 +128,23 @@ void correctMapImage() { // Anti rebound value. Value too low will cause several rebounds of tile // offset rotation ! int m = 50; - if (posx > layer.mapScreenWidth + layer.marginX + m) { - rotateOffsetX = -layer.nbTileX; + if (posx > viewport.mapScreenWidth + viewport.marginX + m) { + rotateOffsetX = -viewport.nbTileX; } else { - if (posx < -layer.marginX - Viewport.tileWidth - m) { - rotateOffsetX = layer.nbTileX; + if (posx < -viewport.marginX - Viewport.tileWidth - m) { + rotateOffsetX = viewport.nbTileX; } } - if (posy > layer.mapScreenHeight + layer.marginY + m) { - rotateOffsetY = -layer.nbTileY; + if (posy > viewport.mapScreenHeight + viewport.marginY + m) { + rotateOffsetY = -viewport.nbTileY; } else { - if (posy < -layer.marginY - Viewport.tileHeight - m) { - rotateOffsetY = layer.nbTileY; + if (posy < -viewport.marginY - Viewport.tileHeight - m) { + rotateOffsetY = viewport.nbTileY; } } if (rotateOffsetX != 0 || rotateOffsetY != 0) { this.fillImage(mapTileX + rotateOffsetX, mapTileY + rotateOffsetY); this.clearImage(); - image = null; - } this.updateMapImage(); } @@ -150,16 +152,30 @@ void correctMapImage() { void fillImage(int tileX, int tileY) { mapTileX = tileX; mapTileY = tileY; - float tw = layer.calcMapTileWidth(); - float th = layer.calcMapTileHeight(); + float tw = viewport.calcMapTileWidth(); + float th = viewport.calcMapTileHeight(); mapx = Math.round(tw * tileX + tw / 2); mapy = Math.round(th * tileY + th / 2); positionImage(); } + + void fillImage() { + float tw = viewport.calcMapTileWidth(); + float th = viewport.calcMapTileHeight(); + mapx = Math.round(tw * mapTileX + tw / 2); + mapy = Math.round(th * mapTileY + th / 2); + positionImage(); + } + void positionImage() { - posx = layer.calcPixelX(0) + Viewport.tileWidth * mapTileX; - posy = layer.calcPixelY(0) + Viewport.tileHeight * mapTileY; + posx = viewport.calcPixelX(0) + Viewport.tileWidth * mapTileX; + posy = viewport.calcPixelY(0) + Viewport.tileHeight * mapTileY; + } + + void positionOldImage() { + posx = viewport.calcOldPixelX(0) + Viewport.tileWidth * mapTileX; + posy = viewport.calcOldPixelY(0) + Viewport.tileHeight * mapTileY; } /** @@ -174,7 +190,8 @@ void clearImage() { image.abortDownload(); } - image = null; + // image = null; + image.state = LoadState.CLEARED; visible = false; JveLog.d(TAG, this + "-task cancelled"); // } @@ -197,8 +214,8 @@ void updateMapImage() { JveLog.d(TAG, this + "-y2 : " + y2); boolean vis = Viewport.rectIntersectRect(x1, x2, y1, y2, - -horizontalMargin - tw, layer.mapScreenWidth + horizontalMargin - + tw, -verticalMargin - th, layer.mapScreenHeight + -horizontalMargin - tw, viewport.mapScreenWidth + horizontalMargin + + tw, -verticalMargin - th, viewport.mapScreenHeight + verticalMargin + th); if (!vis) { if (visible) { @@ -215,8 +232,8 @@ void updateMapImage() { String calcTileSrc = calcTileSrc(); String cacheFileName = calcCacheName(); image.update(calcTileSrc, cacheFileName); -// image = new Image(calcTileSrc, cacheFileName); -// Log.d(TAG, "cache name : " + cacheFileName); + // image = new Image(calcTileSrc, cacheFileName); + // Log.d(TAG, "cache name : " + cacheFileName); } if (!visible) { visible = true; @@ -225,7 +242,7 @@ void updateMapImage() { } private String calcCacheName() { - String scaleString = Integer.toString(layer.scale); + String scaleString = Integer.toString(viewport.scale); String mapTileXS = Integer.valueOf(Math.abs(mapTileX)).toString(); String mapTileYS = Integer.valueOf(Math.abs(mapTileY)).toString(); @@ -234,8 +251,8 @@ private String calcCacheName() { } public String calcTileSrc() { - String src = layer.context.getString(R.string.tileUrl); - String scaleString = Integer.toString(layer.scale); + String src = viewport.context.getString(R.string.tileUrl); + String scaleString = Integer.toString(viewport.scale); String mapTileXS = Integer.valueOf(Math.abs(mapTileX)).toString(); String mapTileYS = Integer.valueOf(Math.abs(mapTileY)).toString(); src = src.replaceAll("!SCALE!", scaleString) @@ -249,4 +266,15 @@ public String toString() { return "Tile" + "-" + indexX + "-" + indexY; } + @Override + protected Object clone() throws CloneNotSupportedException { + + Tile clone = (Tile) super.clone(); + if (image != null) { + clone.image = (Image) this.image.clone(); + } + return clone; + + } + } diff --git a/src/com/hexagon/map/Viewport.java b/src/com/hexagon/map/Viewport.java index 8df2a6e..6e8df02 100755 --- a/src/com/hexagon/map/Viewport.java +++ b/src/com/hexagon/map/Viewport.java @@ -1,6 +1,9 @@ package com.hexagon.map; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -29,12 +32,15 @@ import com.hexagon.map.geo.AbstractPositionableElement; import com.hexagon.map.geo.LocationablePoint; import com.hexagon.map.geo.Point; +import com.hexagon.map.util.JveLog; import com.jhlabs.map.awt.Point2D; import com.jhlabs.map.proj.MercatorProjection; public class Viewport extends AbstractPositionableElement implements LocationListener { + private static final String TAG = "Viewport"; + // Make this bigger will preload more tiles surrounding the screen, making // less checkboard tile, but more bitmap to move, increasing bandwith // requirement. 2 is fastest @@ -68,7 +74,8 @@ public class Viewport extends AbstractPositionableElement implements public int mapScreenHeight; public float centerX; public float centerY; - private Tile[][] images; + private Tile[][] grid1; + private Tile[][] grid2; public boolean running = true; @@ -90,6 +97,8 @@ public class Viewport extends AbstractPositionableElement implements AbstractLocationListener listener; private int newScale; + private int oldScale; + public float zoomScale = 1.0f; public float azimuth_angle; @@ -98,6 +107,7 @@ public class Viewport extends AbstractPositionableElement implements public LocationablePoint locationPoint = new LocationablePoint(); Point targetPoint; + volatile boolean zoomOnGoing; // ////////////////////////////////////////////////////////////// @@ -123,7 +133,8 @@ public void init(Context context, DisplayMetrics dm) { marginY = 0; mapScreenWidth = dm.widthPixels; - mapScreenHeight = dm.heightPixels - 75; +// mapScreenHeight = dm.heightPixels - 75; + mapScreenHeight = dm.heightPixels; int tempX = mapScreenWidth + 2 * marginX; int tempY = mapScreenHeight + 2 * marginY; @@ -133,14 +144,22 @@ public void init(Context context, DisplayMetrics dm) { centerX = mapScreenWidth / 2; centerY = mapScreenHeight / 2; - images = new Tile[nbTileX][nbTileY]; + grid1 = new Tile[nbTileX][nbTileY]; for (int ix = 0; ix < this.nbTileX; ix++) { - images[ix] = new Tile[nbTileY]; + grid1[ix] = new Tile[nbTileY]; for (int iy = 0; iy < this.nbTileY; iy++) { - this.images[ix][iy] = createTile(ix, iy); + this.grid1[ix][iy] = createTile(ix, iy); } + } + grid2 = new Tile[nbTileX][nbTileY]; + for (int ix = 0; ix < this.nbTileX; ix++) { + grid2[ix] = new Tile[nbTileY]; + for (int iy = 0; iy < this.nbTileY; iy++) { + this.grid2[ix][iy] = createTile(ix, iy); + } } + BitmapFactory.Options opt = new BitmapFactory.Options(); // opt.inDither = true; opt.inPreferredConfig = Bitmap.Config.RGB_565; // @@ -213,12 +232,15 @@ public void initPosition() { } public void move() { + if (zoomOnGoing) + return; + for (int ix = 0; ix < nbTileX; ix++) { for (int iy = 0; iy < nbTileY; iy++) { - Tile t = images[ix][iy]; + Tile t = grid1[ix][iy]; t.positionImage(); t.correctMapImage(); - if (!t.visible) { + if (!t.visible && t.image.visibleOnTop) { // Out of syncro, scrolling was too quick, need to recompute // all tiles refresh(); @@ -236,6 +258,14 @@ int calcPixelY(float _3c) { return Math.round(centerY + (_3c - coordY) / zoomRatios[scale]); } + int calcOldPixelX(float _3c) { + return Math.round(centerX + (_3c - coordX) / zoomRatios[oldScale]); + } + + int calcOldPixelY(float _3c) { + return Math.round(centerY + (_3c - coordY) / zoomRatios[oldScale]); + } + private float calcMapDeltaX(float initiaPos, int delta) { return initiaPos + delta * zoomRatios[scale]; } @@ -317,41 +347,70 @@ public List getTilesList() { List result = new ArrayList(); for (int ix = 0; ix < this.nbTileX; ix++) { for (int iy = 0; iy < this.nbTileY; iy++) { - result.add(images[ix][iy]); + result.add(grid1[ix][iy]); + } + } + return result; + + } + + public synchronized List getTilesList2() { + List result = new ArrayList(); + for (int ix = 0; ix < this.nbTileX; ix++) { + for (int iy = 0; iy < this.nbTileY; iy++) { + result.add(grid2[ix][iy]); } } return result; } - public void refresh() { + public synchronized void refresh() { + + if (zoomOnGoing) + return; + newScale = scale; int offsetX = nbTileX / 2; int offsetY = nbTileY / 2; centerX = mapScreenWidth / 2; centerY = mapScreenHeight / 2; - int numTileX = this.calcNumTileX(coordX); - int numTileY = this.calcNumTileY(coordY); + int numTileX = calcNumTileX(coordX); + int numTileY = calcNumTileY(coordY); + + List sortedTiles = new ArrayList(); for (int ix = 0; ix < this.nbTileX; ix++) { for (int iy = 0; iy < this.nbTileY; iy++) { - Tile t = this.images[ix][iy]; - int tileOffsetX = numTileX + ix - offsetX; - int tileOffsetY = numTileY + iy - offsetY; - t.clearImage(); - t.fillImage(tileOffsetX, tileOffsetY); - t.correctMapImage(); - t.updateMapImage(); + Tile t = this.grid1[ix][iy]; + synchronized (t) { + int tileOffsetX = numTileX + ix - offsetX; + int tileOffsetY = numTileY + iy - offsetY; + + t.mapTileX = tileOffsetX; + t.mapTileY = tileOffsetY; + + sortedTiles.add(t); + } } } + + Collections.sort(sortedTiles, new TileComparator(numTileX, numTileY)); + for (Tile t : sortedTiles) { + t.clearImage(); + t.fillImage(); + t.correctMapImage(); + t.updateMapImage(); + } + } - public void zoomIn() { + public synchronized void zoomIn() { scale++; refresh(); } - public void zoomOut() { + public synchronized void zoomOut() { scale--; refresh(); } @@ -392,6 +451,24 @@ public void unlock() { lock = false; } + private final class TileComparator implements Comparator { + + private int numTileX; + private int numTileY; + + public TileComparator(int numTileX, int numTileY) { + this.numTileX = numTileX; + this.numTileY = numTileY; + } + + @Override + public int compare(Tile lhs, Tile rhs) { + int lIndex = lhs.mapTileX - numTileX + lhs.mapTileY - numTileY; + int rIndex = rhs.mapTileX - numTileX + rhs.mapTileY - numTileY; + return rIndex - lIndex; + } + } + private class ScreenScrollAnimation extends Animation { public float vY; public float vX; @@ -450,21 +527,21 @@ public ScreenZoomAnimation() { } @Override - protected void applyTransformation(float interpolatedTime, + protected synchronized void applyTransformation(float interpolatedTime, Transformation t) { float deltaZoom = finalZoom - initialZoom; - - synchronized (getMapActivity().surfaceHolder) { - zoomScale = deltaZoom * interpolatedTime + initialZoom; - } + zoomScale = deltaZoom * interpolatedTime + initialZoom; } @Override - public void onAnimationEnd(Animation animation) { + public synchronized void onAnimationEnd(Animation animation) { + zoomOnGoing = false; + oldScale = scale; scale = newScale; + JveLog.d(TAG, "zoomOnGoing : " + zoomOnGoing); refresh(); - zoomScale = 1.0f; + // zoomScale = 1.0f; } @Override @@ -472,7 +549,8 @@ public void onAnimationRepeat(Animation animation) { } @Override - public void onAnimationStart(Animation animation) { + public synchronized void onAnimationStart(Animation animation) { + zoomOnGoing = true; } } @@ -538,7 +616,8 @@ public void moveToPositionAnimated(Point2D.Float pos) { } } - public void zoomInAnimated() { + public synchronized void zoomInAnimated() { + copyGrid(); newScale++; screenZoomAnimation.initialZoom = 1.0f; screenZoomAnimation.finalZoom = 2.0f; @@ -546,7 +625,8 @@ public void zoomInAnimated() { screenZoomAnimation.start(); } - public void zoomOutAnimated() { + public synchronized void zoomOutAnimated() { + copyGrid(); newScale--; screenZoomAnimation.initialZoom = 1.0f; screenZoomAnimation.finalZoom = 0.5f; @@ -555,19 +635,22 @@ public void zoomOutAnimated() { } public void zoomReset(Float oldScale) { + if (oldScale != null) { screenZoomAnimation.initialZoom = oldScale; + screenZoomAnimation.finalZoom = Math.round(oldScale); } else { screenZoomAnimation.initialZoom = zoomScale; + screenZoomAnimation.finalZoom = Math.round(zoomScale); } - screenZoomAnimation.finalZoom = Math.round(zoomScale); - if (screenZoomAnimation.finalZoom < 0.5f) screenZoomAnimation.finalZoom = 0.5f; - if (screenZoomAnimation.finalZoom > 2.0f) screenZoomAnimation.finalZoom = 2.0f; + if (screenZoomAnimation.finalZoom < 0.5f) + screenZoomAnimation.finalZoom = 0.5f; + if (screenZoomAnimation.finalZoom > 2.0f) + screenZoomAnimation.finalZoom = 2.0f; screenZoomAnimation.initialize(0, 0, 0, 0); screenZoomAnimation.start(); } - public void moveToLastLocation() { moveToLocation(getCurrentBestLocation()); } @@ -610,25 +693,41 @@ public void correctScale() { * @param canvas * @param paint */ - public void draw(Canvas canvas, Paint paint) { + public synchronized void draw(Canvas canvas, Paint paint) { handleAnimations(); paint.setColor(Color.LTGRAY); canvas.drawRect(0, 0, mapScreenWidth, mapScreenHeight, paint); - List tiles = getTilesList(); - m.setScale(zoomScale, zoomScale, mapScreenWidth / 2, + + List tiles; + Matrix m1; + m1 = new Matrix(m); + m1.setScale(zoomScale, zoomScale, mapScreenWidth / 2, mapScreenHeight / 2); + if (!isGridLoaded()) { + tiles = getTilesList2(); + for (Tile t : tiles) { + if (t.visible) { + t.positionOldImage(); + synchronized (t) { + t.draw(canvas, m1, paint); + } + } + } + } + tiles = getTilesList(); + Paint paint2 = new Paint(paint); + // paint2.setAlpha(100); for (Tile t : tiles) { - if (t.visible) { - // t.draw(canvas, mapActivity.scrollX, mapActivity.scrollY, - // paint); - t.draw(canvas, m, paint); + if (t.image.visibleOnTop && !zoomOnGoing) { + t.draw(canvas, m, paint2); } } + Point p = locationPoint; p.getPosFromCoord(this); paint.setColor(Color.RED); - mLocation.set(m); + mLocation.set(zoomOnGoing ? m1 : m); mLocation.preTranslate(p.posx, p.posy); mLocation.preRotate(azimuth_angle, locationPoint.bmp.getWidth() / 2, locationPoint.bmp.getHeight() / 2); @@ -658,4 +757,42 @@ boolean isZoomMin() { return newScale <= MIN_ZOOM; } + public synchronized void copyGrid() { + zoomOnGoing = true; + oldScale = scale; + try { + for (int ix = 0; ix < nbTileX; ix++) { + for (int iy = 0; iy < nbTileY; iy++) { + Tile tileSrc = grid1[ix][iy]; + grid2[ix][iy] = (Tile) tileSrc.clone(); + if (tileSrc.image != null) { + tileSrc.image.visibleOnTop = false; + } + } + } + // zoomScale = 1.0f; + } catch (CloneNotSupportedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public synchronized void zoomAnimated(int zoomOffset) { + newScale += zoomOffset; + + } + + public synchronized boolean isGridLoaded() { + for (int ix = 0; ix < this.nbTileX; ix++) { + for (int iy = 0; iy < this.nbTileY; iy++) { + Tile t = this.grid1[ix][iy]; + boolean v = t.image.visibleOnTop; + boolean opaque = t.image.alpha == 255; + if (zoomOnGoing || !v || !opaque) { + return false; + } + } + } + return true; + } } diff --git a/src/com/hexagon/map/download/CacheBitmapDownloadService.java b/src/com/hexagon/map/download/CacheBitmapDownloadService.java index a80df71..82adb06 100755 --- a/src/com/hexagon/map/download/CacheBitmapDownloadService.java +++ b/src/com/hexagon/map/download/CacheBitmapDownloadService.java @@ -121,6 +121,9 @@ public void getTileBitmap(Image image) { .decodeByteArray(b, 0, length, opt); is.close(); image.bmp = bitmap; + image.state = LoadState.LOADED; + image.visibleOnTop = true; + if (Build.VERSION.SDK_INT >= 12) { Viewport.addBitmapToMemoryCache(image.getCacheFileName(), bitmap); @@ -169,7 +172,9 @@ public DownloadAsyncTask(Image image) { @Override public void run() { - getTileBitmap(image); + synchronized (image) { + getTileBitmap(image); + } } } diff --git a/src/com/hexagon/map/download/HttpBitmapDownloadService.java b/src/com/hexagon/map/download/HttpBitmapDownloadService.java index 8f5967b..62f5426 100755 --- a/src/com/hexagon/map/download/HttpBitmapDownloadService.java +++ b/src/com/hexagon/map/download/HttpBitmapDownloadService.java @@ -78,15 +78,18 @@ public void getHttpBitmap(Image image) { try { DefaultHttpClient httpClient = new DefaultHttpClient(); - httpClient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, - "HexagonMap"); +// httpClient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, +// "HexagonMap"); + httpClient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, + "Android"); httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109); HttpResponse response; image.method = new HttpGet(new URI(image.getSrc())); - image.method.addHeader("Referer", "HexagonMap.fr"); +// image.method.addHeader("Referer", "HexagonMap.fr"); + // image.method.addHeader("Cookie", "jknch=hcnkj; ign=" + // getToken()); // method.addHeader("Cookie", "jknch=hcnkj; ign="); @@ -179,6 +182,8 @@ public void getHttpBitmap(Image image) { } } else { image.state = LoadState.LOADED; + image.visibleOnTop = true; + if (Preferences.isLogging()) { // JveLog.d(TAG, this + "-state=loaded, src = " + getSrc()); } @@ -269,7 +274,9 @@ public DownloadAsyncTask(Image image) { @Override public void run() { - getHttpBitmap(image); + synchronized (image) { + getHttpBitmap(image); + } } }