使用旋转/缩放/翻译在Google地图上定位图像

lux*_*cem 6 javascript google-maps image-manipulation image-rotation

我正在开发用于在谷歌地图上定位图像的用户界面.我从:http://overlay-tiler.googlecode.com/svn/trunk/upload.html开始,这非常接近我想要的.

但是我想要一个旋转工具,一个缩放工具和一个翻译工具(后者存在),而不是3个接触点.

我试图添加一个旋转工具,但它不能像我预期的那样工作:

我在左下角放了一个点来控制旋转(围绕图像的中心).鼠标拖动控制点,我计算其他3个点.

我的代码基于移动器对象,但我更改了onMouseMove函数:

overlaytiler.Rotater.prototype.rotateDot_ = function(dot, theta, origin) {
  dot.x = ((dot.x - origin.x) * Math.cos(theta) - (dot.y - origin.y) * Math.sin(theta)) + origin.x;
  dot.y = ((dot.x - origin.x) * Math.sin(theta) + (dot.y - origin.y) * Math.cos(theta)) + origin.y;
  dot.render();
};

overlaytiler.Rotater.prototype.onMouseMove_ = function(e) {
  var dots = this.controlDots_;
  var center = overlaytiler.Rotater.prototype.getCenter_(dots);

  // Diagonal length
  var r = Math.sqrt(Math.pow(this.x - center.x, 2) + Math.pow(this.y - center.y, 2));
  var old = {
    x: this.x,
    y: this.y
  };

  // Real position
  var newPos = {
    x: this.x + e.clientX - this.cx,
    y: this.y + e.clientY - this.cy
  }

  var newR = Math.sqrt(Math.pow(newPos.x - center.x, 2) + Math.pow(newPos.y - center.y, 2));
  var theta = - Math.acos((2 * r * r - (Math.pow(newPos.x - old.x, 2) + Math.pow(newPos.y - old.y, 2))) / (2 * r * r));

  // Fixed distance position
  this.x = (newPos.x - center.x) * (r / newR) + center.x;
  this.y = (newPos.y - center.y) * (r / newR) + center.y;

  dots[1].x = center.x + (center.x - this.x);
  dots[1].y = center.y + (center.y - this.y);
  dots[1].render();

  overlaytiler.Rotater.prototype.rotateDot_(dots[2], theta, center);
  overlaytiler.Rotater.prototype.rotateDot_(dots[0], theta, center);

  // Render
  this.render();

  this.cx = e.clientX;
  this.cy = e.clientY;
};
Run Code Online (Sandbox Code Playgroud)

不幸的是,精度和角度符号存在问题.

http://jsbin.com/iQEbIzo/4/

在几次旋转之后,图像高度失真,并且仅在一个方向上支持旋转.

我想知道如何才能达到很高的精度并且没有任何失真.

也许我的方法在这里没用(尝试在正确的坐标处移动角落),我试图用画布旋转图像,但我的尝试没有成功.

编辑:完整的工作版本:http://jsbin.com/iQEbIzo/7/

efu*_*fux 3

\n

仅支持一个方向的旋转

\n
\n\n

这是由于计算两个向量之间的角度的方式所致。\n无论鼠标是否位于该点的右侧,它总是会给出相同的向量。我在德国数学板中找到了解决方案(不幸的是,如果不使用 Google 的缓存,我将无法访问该网站:缓存版本)。

\n\n

两个向量

\n\n

请注意,在此示例中,角度 \xce\xb1 两侧相同,而不是您期望的第二个角度 -\xce\xb1 。要查明向量 a 是否始终位于向量 b 的“同一侧”,可以使用此公式。

\n\n
ax*by - ay*bx\n
Run Code Online (Sandbox Code Playgroud)\n\n

这要么是积极的,要么是消极的。您只需将角度的符号更改为 即可\xce\xb1 * -1

\n\n

我修改了你的代码的一些部分。

\n\n
overlaytiler.Rotater.prototype.rotateDot_ = function(dot, theta, origin) {\n    // translate to origin\n    dot.x -= origin.x ;\n    dot.y -= origin.y ;\n\n    // perform rotation\n    newPos = {\n         x: dot.x*Math.cos(theta) - dot.y*Math.sin(theta),\n         y: dot.x*Math.sin(theta) + dot.y*Math.cos(theta)\n    } ;\n    dot.x = newPos.x ;\n    dot.y = newPos.y ;\n\n    // translate back to center\n    dot.x += origin.x ;\n    dot.y += origin.y ;\n\n    dot.render();\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果您想知道我如何旋转积分,请参考此站点此站点

\n\n
overlaytiler.Rotater.prototype.onMouseMove_ = function(e) {                                                 \n    var dots = this.controlDots_;                                                                           \n     var center = overlaytiler.Rotater.prototype.getCenter_(dots);                                           \n\n     // get the location of the canvas relative to the screen                                                                                                        \n     var rect = new Array() ;\n     rect[0] = dots[0].canvas_.getBoundingClientRect() ;\n     rect[1] = dots[1].canvas_.getBoundingClientRect() ;\n     rect[2] = dots[2].canvas_.getBoundingClientRect() ;\n\n     // calculate the relative center of the image\n     var relCenter =  {\n         x: (rect[0].left + rect[2].left) / 2,\n         y: (rect[0].top + rect[2].top) / 2\n     } ;\n\n     // calculate a vector from the center to the bottom left of the image\n     dotCorner = {\n         x: rect[1].left - (rect[1].left - relCenter.x) * 2 - relCenter.x,\n         y: rect[1].top - (rect[1].top - relCenter.y) * 2 - relCenter.y\n     } ;                                                                                                   \n\n     // calculate a vector from the center to the mouse position                                             \n     mousePos = {                                                                                            \n          x: e.clientX - relCenter.x,                                                                           \n          y: e.clientY - relCenter.y                                                                            \n     } ;                                                                                                      \n\n     // calculate the angle between the two vector                                                           \n     theta = calculateAngle(dotCorner, mousePos) ;                                                           \n\n     // is the mouse-vector left of the dot-vector -> refer to the german math board                                                           \n     if(dotCorner.y*mousePos.x - dotCorner.x*mousePos.y > 0) {                                               \n          theta *= -1 ;                                                                                      \n     }                                                                                                       \n\n     // calculate new position of the dots and render them                                                   \n     overlaytiler.Rotater.prototype.rotateDot_(dots[2], theta, center);                                      \n     overlaytiler.Rotater.prototype.rotateDot_(dots[1], theta, center);                                      \n     overlaytiler.Rotater.prototype.rotateDot_(dots[0], theta, center);                                      \n\n     // Render                                                                                               \n     this.render();                                                                                          \n\n     this.cx = e.clientX;                                                                                    \n     this.cy = e.clientY;                                                                                    \n };\n
Run Code Online (Sandbox Code Playgroud)\n\n

你可以看到我写了一些向量计算的函数(只是为了让代码更具可读性):

\n\n
function calculateScalarProduct(v1,v2)\n{\n    return (v1.x * v2.x + v1.y * v2.y) ;\n}\n\nfunction calculateLength(v1)\n{\n    return (Math.sqrt(v1.x*v1.x + v1.y*v1.y)) ;\n}\n\nfunction calculateAngle(v1, v2)\n{\n    return (Math.acos(calculateScalarProduct(v1,v2) / (calculateLength(v1)*calculateLength(v2)))) ;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我的工作解决方案。如果有不明白的地方可以评论,这样我可以让我的回答更全面。

\n\n

工作示例:JSBin

\n\n

哇,这是一场艰难的比赛。

\n