Tengo dos ángulos normalizados (en el rango de 0 a 360 grados) y quiero compararlos usando una puntuación de 0 a 1.
Por ejemplo:
var angle1 = 90; var angle2 = 100; // Something like this, but with respect to the direction the angles pointing to var score = 0.9;
Se me ocurrió el siguiente código:
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));
El problema que tengo es que 0, 90 da el mismo resultado que 0, 270 (0,75), lo cual es lógico pero no útil para comparar los ángulos, ya que apuntan en direcciones opuestas.
Lo que estoy buscando es un método para comparar los ángulos con respecto a la orientación usando una puntuación de 0 a 1. ¿Alguien tiene una idea de cómo podría hacer que esto funcione? ¡Gracias por adelantado!
Edición 1, un ejemplo:
En esta imagen, los ángulos verde, amarillo y rojo están más cerca entre sí, por lo que deberían tener una mayor similitud.
Si yo adivinara:
rojo-verde = 0,9 rojo-naranja = 0,8
Sin embargo, el púrpura está lo más lejos posible del azul.
Así que la similitud debería ser algo como:
púrpura-azul = 0.1
Edición 2, cómo debería funcionar el algoritmo:
Según su descripción, parece que desea destilar de alguna manera la orientación y la separación promedio en un solo valor. No estoy seguro de que eso sea posible debido al alias (que insinúa en su pregunta).
Comparar un par de ángulos como usted describe es simplemente calcular su ángulo mínimo de separación.
Sin embargo, comparar dos conjuntos de ángulos de la manera que usted describe también debe tener en cuenta la diferencia en la orientación relativa entre los dos conjuntos. Dado que cada par podría convertirse en un par [separación, orientación], dos pares podrían puntuarse relativamente en función de la distancia cartesiana.
// 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) );