package net.osmand.plus; import net.osmand.osm.MapUtils; import android.graphics.PointF; import android.graphics.RectF; import android.util.FloatMath; public class RotatedTileBox { private float leftTileX; private float topTileY; private float tileWidth; private float tileHeight; private float rotate; private int zoom; private float rotateCos; private float rotateSin; public RotatedTileBox(float leftTileX, float topTileY, float tileWidth, float tileHeight, float rotate, int zoom) { set(leftTileX, topTileY, tileWidth, tileHeight, rotate, zoom); } public RotatedTileBox(RotatedTileBox r){ set(r.leftTileX, r.topTileY, r.tileWidth, r.tileHeight, r.rotate, r.zoom); } private void init() { float rad = (float) Math.toRadians(this.rotate); rotateCos = FloatMath.cos(rad); rotateSin = FloatMath.sin(rad); } public void set(float leftTileX, float topTileY, float tileWidth, float tileHeight, float rotate, int zoom) { this.leftTileX = leftTileX; if(rotate < 0){ rotate += 360; } else if(rotate > 360){ rotate -= 360; } this.rotate = rotate; this.tileHeight = tileHeight; this.tileWidth = tileWidth; this.topTileY = topTileY; this.zoom = zoom; init(); } public float getRotateCos() { return rotateCos; } public float getRotateSin() { return rotateSin; } public int getZoom() { return zoom; } public float getRotate() { return rotate; } public float getTileHeight() { return tileHeight; } public float getTileWidth() { return tileWidth; } public float getLeftTileX() { return leftTileX; } public float getTopTileY() { return topTileY; } public boolean containsTileBox(RotatedTileBox box) { PointF temp = new PointF(); if(box.getZoom() != zoom){ throw new UnsupportedOperationException(); } box.calcPointTile(0, 0, temp); if(!containsPoint(temp.x, temp.y)){ return false; } box.calcPointTile(box.tileWidth, 0, temp); if(!containsPoint(temp.x, temp.y)){ return false; } box.calcPointTile(0, box.tileHeight, temp); if(!containsPoint(temp.x, temp.y)){ return false; } box.calcPointTile(box.tileWidth, box.tileHeight, temp); if(!containsPoint(temp.x, temp.y)){ return false; } return true; } public RectF calculateLatLonBox(RectF rectF) { float tx = calcPointTileX(tileWidth, 0); float tx2 = calcPointTileX(tileWidth, tileHeight); float tx3 = calcPointTileX(0, tileHeight); float minTileX = Math.min(Math.min(leftTileX, tx), Math.min(tx2, tx3)) ; float maxTileX = Math.max(Math.max(leftTileX, tx), Math.max(tx2, tx3)) ; rectF.left = (float) MapUtils.getLongitudeFromTile(zoom, minTileX); rectF.right = (float) MapUtils.getLongitudeFromTile(zoom, maxTileX); float ty = calcPointTileY(tileWidth, 0); float ty2 = calcPointTileY(tileWidth, tileHeight); float ty3 = calcPointTileY(0, tileHeight); float minTileY = Math.min(Math.min(topTileY, ty), Math.min(ty2, ty3)) ; float maxTileY = Math.max(Math.max(topTileY, ty), Math.max(ty2, ty3)) ; rectF.top = (float) MapUtils.getLatitudeFromTile(zoom, minTileY); rectF.bottom = (float) MapUtils.getLatitudeFromTile(zoom, maxTileY); return rectF; } public boolean containsPoint(float tileX, float tileY) { tileX -= leftTileX; tileY -= topTileY; double tx = rotateCos * tileX - rotateSin * tileY; double ty = rotateSin * tileX + rotateCos * tileY; return tx >= 0 && tx <= tileWidth && ty >= 0 && ty <= tileHeight; } protected PointF calcPointTile(float dx, float dy, PointF p){ float tx = rotateCos * dx + rotateSin * dy + leftTileX; float ty = - rotateSin * dx + rotateCos * dy + topTileY; p.set(tx, ty); return p; } protected float calcPointTileX(float dx, float dy){ return rotateCos * dx + rotateSin * dy + leftTileX; } protected float calcPointTileY(float dx, float dy){ return - rotateSin * dx + rotateCos * dy + topTileY; } public float getRightBottomTileX() { return calcPointTileX(tileWidth, tileHeight); } public float getRightBottomTileY() { return calcPointTileY(tileWidth, tileHeight); } }