1

所以,我使用谷歌地图静态 api v2 从 lat,lng @ zoom 9 获取 256x256 图像(例如)。我对图像像素进行了一些计算,得到了一个 x,y 点数组。我想将图层绘制为折线。

我想将 x,y 像素点数组转换为 lat,lng。

我的伪代码是这样的:

var lat = 35.000,lng=33.000;
var TILE_SIZE = 256;
// google code
function degreesToRadians(deg) {
  return deg * (Math.PI / 180);
}

function radiansToDegrees(rad) {
  return rad / (Math.PI / 180);
}

function bound(value, opt_min, opt_max) {
  if (opt_min != null) value = Math.max(value, opt_min);
  if (opt_max != null) value = Math.min(value, opt_max);
  return value;
}
/** @constructor */
function MercatorProjection() {
  this.pixelOrigin_ = new google.maps.Point(TILE_SIZE / 2,
      TILE_SIZE / 2);
  this.pixelsPerLonDegree_ = TILE_SIZE / 360;
  this.pixelsPerLonRadian_ = TILE_SIZE / (2 * Math.PI);
}

MercatorProjection.prototype.fromLatLngToPoint = function(latLng,
    opt_point) {
  var me = this;
  var point = opt_point || new google.maps.Point(0, 0);
  var origin = me.pixelOrigin_;

  point.x = origin.x + latLng.lng() * me.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.
  var siny = bound(Math.sin(degreesToRadians(latLng.lat())), -0.9999,
      0.9999);
  point.y = origin.y + 0.5 * Math.log((1 + siny) / (1 - siny)) *
      -me.pixelsPerLonRadian_;
  return point;
};

MercatorProjection.prototype.fromPointToLatLng = function(point) {
  var me = this;
  var origin = me.pixelOrigin_;
  var lng = (point.x - origin.x) / me.pixelsPerLonDegree_;
  var latRadians = (point.y - origin.y) / -me.pixelsPerLonRadian_;
  var lat = radiansToDegrees(2 * Math.atan(Math.exp(latRadians)) -
      Math.PI / 2);
  return new google.maps.LatLng(lat, lng);
};
// google code

getLatLngFromXY = function(x,y,zoom){
var scale = Math.pow(2,zoom );

      var projection = new MercatorProjection();
      var worldCoordinateCenter = projection.fromLatLngToPoint(new google.maps.LatLng(lat,lng));
      var pixelOffset = new google.maps.Point((x/scale) || 0,(y/scale) ||0);
      var offest_x = (x > 128) ? worldCoordinateCenter.x + pixelOffset.x: worldCoordinateCenter.x - pixelOffset.x;
      var offest_y = (y > 128) ? worldCoordinateCenter.y + pixelOffset.y :
          worldCoordinateCenter.y - pixelOffset.y;
       var worldCoordinateNewCenter = new google.maps.Point(
          offest_x,
          offest_y
      );
       var newCenter = projection.fromPointToLatLng(worldCoordinateNewCenter);

      var ideal_lat = newCenter.lat(),
          ideal_lng = newCenter.lng();
return {lat: ideal_lat, lng: ideal_lng};
}

var some_list = [{x: 129, y: 124},{x: 118, y: 52},...],
    polyline = [];

for(var i=0; i < some_list.length; i++){
    temp_latlng = getLatLngFromXY(some_list[i].x,some_list[i].y,9);
    polyline.push(new google.maps.LatLng(temp_latlng.lat,temp_latlng.lng);
}

new google.maps.Polyline({
  map: map,
  strokeColor: '#FF0000',
  strokeOpacity: 1.0,
  strokeWeight: 10,
  path: polyline
});

我希望这是有道理的。问题是:因为我正在偏移(我猜),所以我到处都有标记,这与它在静态图像上的外观不同。所以我所做的像素->墨卡托之间的转换是错误的。

谢谢

4

1 回答 1

2

我能够解决这个问题......很难理解什么是错的以及需要做什么,基本上我们想要依赖于 ZOOM(上面的比例)

这意味着我们的代码应该改变(“谷歌代码”部分)如下:

MercatorProjection.prototype.fromLatLngToPoint = function(latLng, zoom, opt_point) {
  var me = this;
  var point = opt_point || new google.maps.Point(0, 0);
  var origin = me.pixelOrigin_;

  point.x = origin.x + latLng.lng() * me.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.
  var siny = bound(Math.sin(degreesToRadians(latLng.lat())), -0.9999, 0.9999);
  point.y = origin.y + 0.5 * Math.log((1 + siny) / (1 - siny)) *
      -me.pixelsPerLonRadian_;
  var tiles_no = 1 << zoom;
  point.x *= tiles_no;
  point.y *= tiles_no;

  return point;
};

MercatorProjection.prototype.fromPointToLatLng = function(point, zoom) {
  var me         = this;
  var origin     = me.pixelOrigin_;

  var tiles_no   = 1 << zoom;
  point.x        /= tiles_no;
  point.y        /= tiles_no;
  var lng        = (point.x - origin.x ) / me.pixelsPerLonDegree_;
  var latRadians = (point.y - origin.y) / -me.pixelsPerLonRadian_;
  var lat        = radiansToDegrees(2 * Math.atan(Math.exp(latRadians)) -Math.PI / 2);
  return new google.maps.LatLng(lat, lng);
};

之后,当我们想要从 lat,lng 转换为点时:

var worldCoordinateCenter = projection.fromLatLngToPoint(new google.maps.LatLng(lat,lng),zoom);
and also the offset changes (just for comfort and logic, its almost the same)
var offset_x = (x > (TILE_SIZE / 2)) ?  x - (TILE_SIZE / 2):  -Math.abs(x - (TILE_SIZE / 2));
          var offset_y = (y > (TILE_SIZE / 2)) ?  y - (TILE_SIZE / 2):  -Math.abs(y - (TILE_SIZE / 2));

var newCenter =  projection.fromPointToLatLng({x: worldCoordinateCenter.x + offset_x,y:worldCoordinateCenter.y + offset_y },zoom);

而已。

注意 "1 << zoom" 就像 Math.pow(2,zoom); 还有在 fromLatLngToPoint 我们乘以它(它是每个缩放级别的图块数),在 fromPointToLatLng 我们除以它

于 2013-08-27T15:09:52.493 回答