钻石上的像素座标 [英] pixel coordinates on diamond

查看:61
本文介绍了钻石上的像素座标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到一个图像,其中有几个并排放置的钻石,如下图所示

I got an image with a couple of diamond put side by side like on the image below

我在图像上知道的唯一坐标是顶角(绿色文本).
当我单击图像时,我得到了该点的坐标,但是我无法获得我所在的钻石.
例如,我单击红点,我如何知道x:260,y:179 =顶部钻石?
而蓝色属于左边?等等

The only coordinates I know on the image are the top corners (green text).
When I click on the image I get the coordinates of that point, but I'm not able to get which diamond I'm on.
For example I click on the red dot, how do I know that x:260, y:179 = the top diamond ?
And the blue belongs to the left ? etc...

非常感谢您的帮助.


我最终使用了Canvas,但我认为SVG可以很好地满足我的需要.


I finally used Canvas, but I think SVG would have worked as well for what I needed to do.

推荐答案

我看到了两种可能的方法:直接检查点是否在菱形内部以及使用仿射变换.我将同时描述两者.

I see two possible approaches: direct check whether a point is inside a diamond and using affine transformations. I will describe both.

要确定某个点是否在菱形内部,必须检查其与菱形中点的偏差.您必须将X和Y偏差与菱形的X和Y范围成比例放置,您将获得两个因素.对于菱形内的所有点,这些因子的模值总和小于或等于1.在代码中如下所示:

To determine whether a point is inside a diamond you have to check its deviation from the middle point of a diamond. You have to put the X and Y deviations in proportion with the X and Y extents of the diamond, you will get two factors. For all points inside the diamond the sum of the modulo values for these factors is smaller or equal 1. In code this looks like this:

var dx = Math.abs(coords[0] - middle[0]);
var dy = Math.abs(coords[1] - middle[1]);
if (dx / size[0] + dy / size[1] <= 1)
  alert("Inside diamond");
else
  alert("Outside diamond");

因此,您现在要做的就是确定每个菱形的中间点(大小在所有情况下都相同),并检查您要测试的点是否位于其中.

So all you have to do now is determining the middle point for each diamond (size is the same in all cases) and checking whether the point you are testing is located inside them.

工作示例: http://jsfiddle.net/z98hr/

使用仿射变换,您可以将顶部菱形的角坐标更改为(0,0),(1, 0),(0,1)和(1,1).然后,如果将相同的变换应用于需要测试的点,则确定其所属的钻石就变得微不足道了.

Using affine transformations you can change the corner coordinates of your top diamond into (0,0), (1,0), (0,1) and (1,1). If you then apply the same transformation to the point you need to test, determining which diamond it belongs to becomes trivial.

首先,您需要一个平移矢量才能将(225,2)点移到坐标原点.假设您有四个坐标确定顶部菱形(左坐标和右坐标,顶坐标和底坐标):

First you will need a translation vector to move the (225,2) point into the origin of coordinates. Let's say that you have four coordinates determining your top diamond (left and right coordinate, top and bottom coordinate):

var topDiamond = [[113, 2], [337, 227]];

然后通过平移矢量将钻石的顶部移至零坐标,是:

Then the translation vector to move the top point of the diamond to the zero coordinate would be:

var translationVector = [-(topDiamond[0][0] + topDiamond[1][0]) / 2,
                         -topDiamond[0][1]];

您可以将其应用于原始坐标,如下所示:

You can apply it to the original coordinates like this:

function add(vector1, vector2)
{
  return [vector1[0] + vector2[0], vector1[1] + vector2[1]];
}
topDiamond = [add(topDiamond[0], translationVector),
              add(topDiamond[1], translationVector)];

然后,您将需要旋转矩阵:

var angle = -Math.atan2(topDiamond[1][1] - topDiamond[0][1],
                        topDiamond[1][0] - topDiamond[0][0]);
var rotMatrix = [[Math.cos(angle), -Math.sin(angle)],
                 [Math.sin(angle), Math.cos(angle)]];

与该矩阵相乘后,点(225,2)和(337,114.5)在X轴上对齐.但是现在您有了飞人,现在需要水平剪切变换,以使钻石的另一侧对齐Y轴:

After the multiplication with this matrix the points (225,2) and (337,114.5) are aligned on the X axis. But what you have now is a trapeze, you now need a horizontal shear transformation to get the other side of the diamond aligned on the Y axis:

function multiply(matrix, vector)
{
  return [matrix[0][0] * vector[0] + matrix[0][1] * vector[1],
          matrix[1][0] * vector[0] + matrix[1][1] * vector[1]];
}
var point = [topDiamond[0][0], (topDiamond[0][1] + topDiamond[1][1]) / 2];
point = multiply(rotMatrix, point);
var shearMatrix = [[1, -point[0] / point[1]], [0, 1]];

与该矩阵相乘后,您现在有了一个矩形.现在,您只需要缩放矩阵即可确保角的X和Y坐标具有值0和1:

After multiplication with this matrix you have a rectangle now. Now you only need a scaling matrix to make sure that the X and Y coordinates of the corners have the value 0 and 1:

point = multiply(shearMatrix, point);
var point2 = [topDiamond[1][0], (topDiamond[0][1] + topDiamond[1][1]) / 2];
point2 = multiply(rotMatrix, point2);
point2 = multiply(shearMatrix, point2);
var scaleMatrix = [[1/point2[0], 0], [0, 1/point[1]]];

有了它,现在您可以将这些转换应用于任何点:

And there you have it, now you can apply these transformations to any point:

alert(
  multiply(scaleMatrix,
    multiply(shearMatrix,
      multiply(rotMatrix,
        add(translationVector, [260, 179])
      )
    )
  )
);

这为您提供0.94,0.63-两个值都在(0..1)范围内,这意味着它是顶级钻石.使用[420,230]作为输入,您将得到1.88,0.14-X在(1..2)范围内,Y在0..1范围内表示正确的菱形.依此类推.

This gives you 0.94,0.63 - both values are in the (0..1) range meaning that it is the top diamond. With [420,230] as input you get 1.88,0.14 - X in (1..2) range and Y in 0..1 range means right diamond. And so on.

工作示例: http://jsfiddle.net/FzWHe/

在回顾中,对于像钻石这样的简单几何图形来说,这可能是太多的工作了.

In the retrospective, this was probably too much work for a simple geometrical figure like a diamond.

这篇关于钻石上的像素座标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆