我有一对夫妇的钻石的图像放在并排像下面的图片
我知道在图像上的唯一坐标顶角(绿色文本)。
当我点击图片,我得到的点的坐标,但我没能得到我上的钻石。
例如,我一下就红了点,我怎么知道X:260,Y:179 =顶级钻石?
和蓝色属于左侧? 等等...
非常感谢您的帮助。
编辑:
我终于用画布,但是我觉得SVG会工作,以及什么我需要做的。
我有一对夫妇的钻石的图像放在并排像下面的图片
我知道在图像上的唯一坐标顶角(绿色文本)。
当我点击图片,我得到的点的坐标,但我没能得到我上的钻石。
例如,我一下就红了点,我怎么知道X:260,Y:179 =顶级钻石?
和蓝色属于左侧? 等等...
非常感谢您的帮助。
编辑:
我终于用画布,但是我觉得SVG会工作,以及什么我需要做的。
我看到两种可能的方法:直接检查点是否是钻石内部,使用仿射变换。 我将描述这两种。
要确定一个点是否是你必须从钻石的中间点检查其偏差的钻石内。 你必须把X和Y的偏差与钻石的X和Y范围的比例,你会得到两个因素。 对于所有点金刚石内的模值的这些因素的总和小于或等于1。在这个代码看起来是这样的:
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");
所以,你现在要做的是确定的中间点,每颗钻石(大小在所有情况下相同),并检查你正在测试点是否位于它们内部。
工作示例: http://jsfiddle.net/z98hr/
使用仿射变换 ,你可以改变你的顶级钻石的顶点坐标为(0,0),(1,0),(0,1)和(1,1)。 如果再采用同样的改造,你需要测试点,确定它属于哪个钻石变得微不足道。
首先,你需要一个转换向量到(225,2)点移动到坐标原点。 比方说,你有四个坐标确定你的顶级钻石(左,右协调,顶部和底部坐标):
var topDiamond = [[113, 2], [337, 227]];
然后平移向量移动钻石零协调会的最高点:
var translationVector = [-(topDiamond[0][0] + topDiamond[1][0]) / 2,
-topDiamond[0][1]];
你可以把它应用到原始坐标如下:
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轴对准钻石的另一面:
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:
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]]];
有你有它,现在你可以将这些转换到任意时间点:
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
范围是指正确的钻石。 等等。
工作示例: http://jsfiddle.net/FzWHe/
在回顾,这可能是像钻石一样的简单几何图形的工作太多了。
从本质上讲,你有什么有可能是4个图块的等角视图(基于你对显示为梯形钻石评论)。
这样做的一个快速方法是创建两行是与的“钻石”中的“轴”平行(但仍是穿越对方......这也是很重要的)。 在给出的实例中的图像,这将意味着两行是互相垂直的,但旋转了45度。 在等距的情况下,线不会相互垂直,但在其他一些角度取决于你图。
一旦你有这两条线,你可以创建一个“则hitTest()”功能,将采取被点击的点的坐标,将评估这两个线方程。 你是不是由线方程,但只有体征恢复实际数目很感兴趣。 该标志显示了该行的端做你点所在。
这意味着你的 “钻石” 将对应于这些符号对(每线方程一个符号) - , - ],[ - ,+],[+, - ],[+,+]。
(请注意,符号取决于该行的定义,换言之,针对一个给定的点P,一些线方程(L)的标志将是不同的,如果行被定义为运行“从左至右”的方式或“从右到左”,或更一般地,符号将是相互方向相反。)
可以得到你所需要的直线方程的形式更多的信息从这里
使用矩阵,你可以得到你选择了其中的钻石快速公式。
你想从一个转换(x,y)
为“钻石空间”。 也就是说,一个坐标系,其中(0,0)
是顶金刚石, (1,0)
是一个下面的权利,和(0,1)
下面的左边。
A * x = y
其中A
是变换, x
是图像坐标,和y
是钻石坐标。 为应对翻译( (0,0)
不是在两个空间中的相同点),您可以添加另一行向量,这始终是1
。
您可以在同一时间变换多种载体,通过将它们彼此身边,让他们形成一个矩阵。
[ a b dx ] [ 225 337 113 ] [ 0 1 0 ]
[ c d dy ] * [ 2 114 114 ] = [ 0 0 1 ]
[ 0 0 1 ] [ 1 1 1 ] [ 1 1 1 ]
^ ^ ^-left ^-^-^--- new coordinates for each point
| '-right
'-top diamond
为了解决在第一矩阵中的系数,则需要由第二矩阵,以划分(或由逆相乘)。
[ a b dx ] [ 0 1 0 ] [ 225 337 113 ]^-1
[ c d dy ] = [ 0 0 1 ] * [ 2 114 114 ]
[ 0 0 1 ] [ 1 1 1 ] [ 1 1 1 ]
其结果是:
[ a b dx ] [ (1/224) (1/224) (-227/224) ]
[ c d dy ] = [ (-1/224) (1/224) (223/224) ]
[ 0 0 1 ] [ 0 0 1 ]
为了把这个成程序代码:
function getDiamond(x, y) {
return [(x + y - 227) / 224, (-x + y + 223) / 224];
}
例:
> getDiamond(260,179); // red
[0.9464285714285714, 0.6339285714285714]
> getDiamond(250,230); // green
[1.1294642857142858, 0.90625]
> getDiamond(189,250); // blue
[0.9464285714285714, 1.2678571428571428]
> getDiamond(420,230); // yellow
[1.8883928571428572, 0.14732142857142858]
如果你看的整数部分,您可以看到钻石的坐标对应。 红色的是在(0.94, 0.63)
其是在区域(0,0)
相当接近的边缘(1,0)
NB。 在OP蓝色和绿色的点在错误的位置绘制(或给出错误的坐标),所以我的函数的结果将它们放置在不同的相对位置。
如果你的计算象征,你结束了这一点:
[ a b dx ] [ (y2 - y0)/M -(x2 - x0)/M -(x0*y2 - y0*x2)/M ]
[ c d dy ] = [-(y1 - y0)/M (x1 - x0)/M (x0*y1 - y0*x1)/M ]
[ 0 0 1 ] [ 0 0 1 ]
其中M = x1*y2 - x2*y1 - y0*x1 + y0*x2 + x0*y1 - x0*y2
。
点0是顶部金刚石的位置,点1为右金刚石的位置,和第2点是左金刚石的位置。
这里是计算这样的功能:
function DiamondMaker(topx,topy, leftx,lefty, rightx,righty)
{
var M = topx*lefty - topx*righty +
leftx*righty - leftx*topy +
rightx*topy - rightx*lefty;
var a = -(topy - righty)/M;
var b = (topx - rightx)/M;
var dx = -(topx*righty - topy*rightx)/M;
var c = (topy - lefty)/M;
var d = -(topx - leftx)/M;
var dy = (topx*lefty - topy*leftx)/M;
return function(x, y) {
return [a * x + b * y + dx, c * x + d * y + dy];
};
}
var getDiamond = DiamondMaker(225,2, 337,114, 113,114);
// (same example as before)
所有你需要的 - 只是stady是什么roration。 这里是链接: http://en.wikipedia.org/wiki/Rotation_(mathematics )
你应该转动你为了使广场的两侧与协调的电网parrallel点。 rotaion点应该是dimonds 1个角落,你会威胁0,0钻石。 rotaion后,你可以很容易地定义你从0,0点离开多少daimond