拼贴投影Google地图:将距离转换为屏幕尺寸 [英] Tile Projection Google Maps: Convert Distance to Screen Dimensions
问题描述
我在Google Maps Android v2中使用CanvasTileProvider。
我可以将纬度长点转换为屏幕像素。
但是我想创建一个方法将距离转换为屏幕像素。这将允许我绘制一个x半径的圆。任何人都可以帮忙吗?
下面的代码在其他地方被屠杀和修改,所以相信原作者。
/ **
*在LatLng坐标和图块内的像素之间进行转换。
* /
public class TileProjection {
public int x;
public int y;
private int zoom;
private int TILE_SIZE;
私人DoublePoint pixelOrigin_;
private double pixelsPerLonDegree_;
私人双像素PerLonRadian_;
TileProjection(int tileSize,int x,int y,int zoom){
this.TILE_SIZE = tileSize;
this.x = x;
this.y = y;
this.zoom = zoom;
pixelOrigin_ =新的DoublePoint(TILE_SIZE / 2,TILE_SIZE / 2);
pixelsPerLonDegree_ = TILE_SIZE / 360d;
pixelsPerLonRadian_ = TILE_SIZE /(2 * Math.PI);
$ b / **
*以LatLng坐标获取Tile的尺寸
* /
public LatLngBounds getTileBounds(){
DoublePoint tileSW =新的DoublePoint(x * TILE_SIZE,(y + 1)* TILE_SIZE);
DoublePoint worldSW = pixelToWorldCoordinates(tileSW);
LatLng SW = worldCoordToLatLng(worldSW);
DoublePoint tileNE =新的DoublePoint((x + 1)* TILE_SIZE,y * TILE_SIZE);
DoublePoint worldNE = pixelToWorldCoordinates(tileNE);
LatLng NE = worldCoordToLatLng(worldNE);
返回新的LatLngBounds(SW,NE);
}
/ **
*计算图块内的像素坐标,相对于图块的左上角
*角(原点)。
* /
public PointF latLngToPoint(LatLng latLng){
DoublePoint result = new DoublePoint(1,1);
// Log.d(Aero,x+ String.valueOf(x));
// Log.d(Aero,y+ String.valueOf(y));
latLngToWorldCoordinates(latLng,result);
worldToPixelCoordinates(result,result);
result.x - = x * TILE_SIZE;
int numTiles = 1<<放大;
if(latLng.longitude <0){
result.x = result.x +(numTiles * TILE_SIZE);
}
result.y - = y * TILE_SIZE;
返回新的PointF((float)result.x,(float)result.y);
}
private DoublePoint pixelToWorldCoordinates(DoublePoint pixelCoord){
int numTiles = 1<<放大;
DoublePoint worldCoordinate =新的DoublePoint(pixelCoord.x / numTiles,
pixelCoord.y / numTiles);
return worldCoordinate;
}
/ **
*将世界坐标转换为相对于
*整个图块区域的像素坐标。 (即跨越所有图块的坐标系)。
*< p />
*< p />
*将得到的点作为参数,以避免创建新对象。
* /
private void worldToPixelCoordinates(DoublePoint worldCoord,DoublePoint结果){
int numTiles = 1<<放大;
result.x = worldCoord.x * numTiles;
result.y = worldCoord.y * numTiles;
}
private LatLng worldCoordToLatLng(DoublePoint worldCoordinate){
DoublePoint origin = pixelOrigin_;
double lng =(worldCoordinate.x - origin.x)/ pixelsPerLonDegree_;
double latRadians =(worldCoordinate.y - origin.y)
/ -pixelsPerLonRadian_;
double lat = Math.toDegrees(2 * Math.atan(Math.exp(latRadians))
- Math.PI / 2);
返回新的LatLng(lat,lng);
$ b / **
*获取描述整个地球的系统坐标,坐标为
*,范围从0到TILE_SIZE(double类型)。
*< p />
*将得到的点作为参数,以避免创建新对象。
* /
private void latLngToWorldCoordinates(LatLng latLng,DoublePoint结果){
DoublePoint origin = pixelOrigin_;
result.x = origin.x + latLng.longitude * pixelsPerLonDegree_;
//截断为0.9999将纬度限制为89.189。这是
//大约三分之一的瓦片超过了世界瓦片的边缘。
double siny = bound(Math.sin(Math.toRadians(latLng.latitude)),-0.9999,
0.9999);
result.y = origin.y + 0.5 * Math.log((1 + siny)/(1 - siny))
* -pixelsPerLonRadian_;
}
;
/ **
*如果在这些界限之外,则返回值降至最小值和最大值。
* /
私人双重限制(双倍值,双倍最大值,双倍最大值){
值= Math.max(值,最小值);
value = Math.min(value,max);
返回值;
$ b $ **
*坐标为double
* /
的x / y坐标系中的一个点public static class DoublePoint {
double x;
double y;
public DoublePoint(double x,double y){
this.x = x;
this.y = y;
$ b $ / code>
这是我建议使用:
public Double MetersToPixels(LatLng latLng,Double distance){
double tileScale = TILE_SIZE / 256;
double pixelsPerMeter = 1 /(156543.03392 * Math.cos(latLng.latitude * Math.PI / 180)/ Math.pow(2,zoom))* tileScale;
返回pixelsPerMeter *距离;
起初,您应该了解事实上,地球表面上的一个圆并不完全是地图上的一个圆。但是如果你忽略这个不准确性,你只需要在25nm的距离创建一个LatLng点,然后使用latLngToPoint方法来获取像素。将它们与中心的像素进行比较,可以给出半径。要在给定距离内创建LatLng,请参阅此答案 SO问题(方法移动)
I am using the CanvasTileProvider in Google Maps Android v2.
I can convert lat long points to screen pixels.
However I would like to create a method to convert a distance to screen pixels. This will allow me to draw a circle of x radius. Can anyone help with this?
The code below I have butchered and modified from somewhere else so credit to the original author.
/**
* Converts between LatLng coordinates and the pixels inside a tile.
*/
public class TileProjection {
public int x;
public int y;
private int zoom;
private int TILE_SIZE;
private DoublePoint pixelOrigin_;
private double pixelsPerLonDegree_;
private double pixelsPerLonRadian_;
TileProjection(int tileSize, int x, int y, int zoom) {
this.TILE_SIZE = tileSize;
this.x = x;
this.y = y;
this.zoom = zoom;
pixelOrigin_ = new DoublePoint(TILE_SIZE / 2, TILE_SIZE / 2);
pixelsPerLonDegree_ = TILE_SIZE / 360d;
pixelsPerLonRadian_ = TILE_SIZE / (2 * Math.PI);
}
/**
* Get the dimensions of the Tile in LatLng coordinates
*/
public LatLngBounds getTileBounds() {
DoublePoint tileSW = new DoublePoint(x * TILE_SIZE, (y + 1) * TILE_SIZE);
DoublePoint worldSW = pixelToWorldCoordinates(tileSW);
LatLng SW = worldCoordToLatLng(worldSW);
DoublePoint tileNE = new DoublePoint((x + 1) * TILE_SIZE, y * TILE_SIZE);
DoublePoint worldNE = pixelToWorldCoordinates(tileNE);
LatLng NE = worldCoordToLatLng(worldNE);
return new LatLngBounds(SW, NE);
}
/**
* Calculate the pixel coordinates inside a tile, relative to the left upper
* corner (origin) of the tile.
*/
public PointF latLngToPoint(LatLng latLng) {
DoublePoint result = new DoublePoint(1, 1);
// Log.d("Aero","x " + String.valueOf(x));
// Log.d("Aero","y " + String.valueOf(y));
latLngToWorldCoordinates(latLng, result);
worldToPixelCoordinates(result, result);
result.x -= x * TILE_SIZE;
int numTiles = 1 << zoom;
if (latLng.longitude < 0) {
result.x = result.x + (numTiles * TILE_SIZE);
}
result.y -= y * TILE_SIZE;
return new PointF((float) result.x, (float) result.y);
}
private DoublePoint pixelToWorldCoordinates(DoublePoint pixelCoord) {
int numTiles = 1 << zoom;
DoublePoint worldCoordinate = new DoublePoint(pixelCoord.x / numTiles,
pixelCoord.y / numTiles);
return worldCoordinate;
}
/**
* Transform the world coordinates into pixel-coordinates relative to the
* whole tile-area. (i.e. the coordinate system that spans all tiles.)
* <p/>
* <p/>
* Takes the resulting point as parameter, to avoid creation of new objects.
*/
private void worldToPixelCoordinates(DoublePoint worldCoord, DoublePoint result) {
int numTiles = 1 << zoom;
result.x = worldCoord.x * numTiles;
result.y = worldCoord.y * numTiles;
}
private LatLng worldCoordToLatLng(DoublePoint worldCoordinate) {
DoublePoint origin = pixelOrigin_;
double lng = (worldCoordinate.x - origin.x) / pixelsPerLonDegree_;
double latRadians = (worldCoordinate.y - origin.y)
/ -pixelsPerLonRadian_;
double lat = Math.toDegrees(2 * Math.atan(Math.exp(latRadians))
- Math.PI / 2);
return new LatLng(lat, lng);
}
/**
* Get the coordinates in a system describing the whole globe in a
* coordinate range from 0 to TILE_SIZE (type double).
* <p/>
* Takes the resulting point as parameter, to avoid creation of new objects.
*/
private void latLngToWorldCoordinates(LatLng latLng, DoublePoint result) {
DoublePoint origin = pixelOrigin_;
result.x = origin.x + latLng.longitude * pixelsPerLonDegree_;
// Truncating to 0.9999 effectively limits latitude to 89.189. This is
// about a third of a tile past the edge of the world tile.
double siny = bound(Math.sin(Math.toRadians(latLng.latitude)), -0.9999,
0.9999);
result.y = origin.y + 0.5 * Math.log((1 + siny) / (1 - siny))
* -pixelsPerLonRadian_;
}
;
/**
* Return value reduced to min and max if outside one of these bounds.
*/
private double bound(double value, double min, double max) {
value = Math.max(value, min);
value = Math.min(value, max);
return value;
}
/**
* A Point in an x/y coordinate system with coordinates of type double
*/
public static class DoublePoint {
double x;
double y;
public DoublePoint(double x, double y) {
this.x = x;
this.y = y;
}
}
}
This is what I am proposing to use:
public Double MetersToPixels(LatLng latLng, Double distance){
double tileScale = TILE_SIZE / 256;
double pixelsPerMeter =1 / (156543.03392 * Math.cos(latLng.latitude * Math.PI / 180) / Math.pow(2, zoom)) * tileScale;
return pixelsPerMeter * distance;
}
At first you should be aware of the fact, that a circle on the surface of the earth is not exactly a circle on the map. But if you ignore this inaccuracy, you just need to create a LatLng point in 25nm distance, and then use latLngToPoint method to get the pixels. Comparing them with the pixels of the center, gives you the radius. For creating a LatLng in a given distance see the answer to this SO question (method move)
这篇关于拼贴投影Google地图:将距离转换为屏幕尺寸的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!