/**
* Copyright (c) 2009-2011, chunquedong(YangJiandong)
*
* This file is part of ChunMap project
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE(Version >=3)
*
* History:
* 2010-05-05 Jed Young Creation
*/
package chunmap.raster.gmap;
import java.util.ArrayList;
import java.util.List;
import chunmap.model.coord.CPoint;
import chunmap.model.crs.proj.Mercator;
import chunmap.model.elem.Envelope;
import chunmap.raster.Tile;
public class GoogleMapCode {
public static final int tileSize = 256;//每个瓦片的像素大小
public static final double dis = Mercator.maxDis * 2;//墨卡托投影展开的宽度
public static final double originScale = tileSize / dis;//一个瓦片显示全球时的比例尺
private int countX;
private double sizeX;
private void init(int zoom)
{
countX = (int)Math.pow(2, zoom);//水平或者垂直Tile个数
sizeX = dis / countX;//每个Tile的大小,投影坐标下
}
public List<GMTile> getTileSet(Envelope envelope, double scale)
{
List<GMTile> tileSet = new ArrayList<GMTile>();
int zoom = scale2zoom(scale);
if (zoom < 0)
{
GMTile t = new GMTile(0, 0, 0);
tileSet.add(t);
return tileSet;
}
//初始化参数
init(zoom);
GMTile minT = getTile(zoom, envelope.leftUp(), countX, sizeX,true);
GMTile maxT = getTile(zoom, envelope.rightDown(), countX, sizeX,false);
for (int i = minT.x; i <= maxT.x; i++)
{
for (int j = minT.y; j <= maxT.y; j++)
{
GMTile tile = new GMTile(i, j, zoom);
normallize(tile, countX);
tileSet.add(tile);
}
}
return tileSet;
}
//由比例尺计算zoom
private int scale2zoom(double scale)
{
double curScale = originScale;
int i = -1;
while (curScale < scale*1.5)
{
curScale = curScale * 2d;
i++;
}
return i;
}
//由点坐标得到瓦片坐标
private GMTile getTile(int zoom, CPoint p, int countX, double sizeX
, boolean isLeftUp)
{
double indexX = (p.getX() + Mercator.maxDis) / sizeX;
double indexY = (Mercator.maxDis - p.getY()) / sizeX;
if (isLeftUp)
{
indexX = indexX - 1;
indexY = indexY - 1;
}
int ix = (int)indexX;
int iy = (int)indexY;
return new GMTile(ix, iy, zoom);
}
//正规化瓦片
private void normallize(GMTile tile, int count)
{
int n = subNormalize(tile.x, count);
if (n != -1)
{
tile.createProxy();
tile.proxy.x = n;
}
int n2 = subNormalize(tile.y, count);
if (n2 != -1)
{
tile.createProxy();
tile.proxy.y = n2;
}
}
private int subNormalize(int x, int c)
{
if (x >= c)
{
return x % c;
}
else if (x < 0)
{
int t = x % c;
if (t >= 0) return t;
return t + c;
}
else
{
return -1;
}
}
/// <summary>
/// 得到tile所占的Envelope
/// </summary>
/// <param name="tile"></param>
/// <returns></returns>
public Envelope getEnvelope(Tile tile)
{
int countX = (int)Math.pow(2, (tile.z));//水平或者垂直Tile个数
double sizeX = dis / countX;//每个Tile的大小,投影坐标下
double minX = (tile.x * sizeX) - Mercator.maxDis;
double maxY = Mercator.maxDis - (tile.y * sizeX);
return new Envelope(minX, maxY-sizeX, minX + sizeX, maxY);
}
}