计算角度相似度 - 数学 - JavaScript

Calculate Angle Similarity - Math - JavaScript

我有两个归一化角度(在 0 到 360 度范围内),想用 0 到 1 的分数来比较它们。

例如:

var angle1 = 90;
var angle2 = 100;

// Something like this, but with respect to the direction the angles pointing to

var score = 0.9;

我想出了以下代码:

function modulo(x, y){

    return (x % y + y) % y;

}

// Calculates the closest distance between the two angles

var relativeAngle = angle2 - angle1;
relativeAngle = modulo((relativeAngle + 180), 360) - 180;
  
// Converts the result to a score and logs the result
  
console.log(1 - (Math.abs(relativeAngle) / 360));

我遇到的问题是 0, 90 给出与 0, 270 (0.75) 相同的结果,这是合乎逻辑的,但对于比较指向相反方向的角度没有用。

我正在寻找的是一种使用 0 到 1 之间的分数来比较相对于方向的角度的方法。有谁知道我如何让它工作?提前致谢!

编辑1,例子:

这张图中绿色、黄色和红色的角度比较接近,所以它们应该有更高的相似度。

如果我猜的话:

红-绿=0.9 红橙色 = 0.8

然而,紫色离蓝色越远越好。

所以相似度应该是这样的:

紫-蓝 = 0.1

编辑 2,算法应该如何工作:

根据您的描述,您似乎想以某种方式将平均方向和分离度提炼成一个值。由于别名(您在问题中暗示),我不确定这是否可能。

按照您的描述比较一对角,只是计算它们的最小分离角。

但是按照你描述的方式比较两组角度还需要考虑到两组之间的相对方位的差异。由于每对都可以转换为[分离,方向]对,因此可以根据笛卡尔距离对两对进行相对评分。

// Smallest difference between angles as on a circle
// range [0, 1)
const angle = (a,b) => {
  const results = a > b ? a - b : b - a;
  return (results > 180 ? 360 - results : results) / 180;
}

// Midway between two angles as on a circle
// range [0, 1)
const direction = (a,b) => {
  const large = (a > b ? a - b : b - a) > 180;
  const results = (a + b) / 2;
  return (results + (large ? (results >= 180 ? -180 : 180 ) : 0)) / 180;
};

// Cartesian distance score
// range [0, 1)
// x is angle, y is direction
const distance = (x0, y0, x1, y1) => {
  // direction wraps around so account for that
  if((y0 > y1 ? y0 - y1 : y1 - y0) > 0.5) y0 += 1;

  // the `*2` is because the wrap-around distance is never more than half the interval. 
  return Math.sqrt((x0-x1)**2 + ((y0-y1)*2)**2) / Math.SQRT2;
}

// Difference score for two angles, a and b
const diff = (a,b) => angle(a, b);

// Difference score for two pairs of angles [[a0, b0], [a1, b1]]
const diff2 = (a0, b0, a1, b1) => distance(
  angle(a0, b0), direction(a0, b0),
  angle(a1, b1), direction(a1, b1)
);