L'obtention de la différence entre les deux têtes de
-
14-11-2019 - |
Question
J'ai cette méthode pour comprendre la différence entre les 2 0-360 boussole en-têtes.
Bien que cela fonctionne pour déterminer dans quelle mesure absolument (comme dans, toujours de sortie positive) hors je suis, j'ai du mal à déterminer ce qui doit être fait pour introduire le signe sur la sortie.
Idéalement, si la distance la plus courte à partir de l'initiale de la tête à la finale de la rubrique est en allant dans le sens horaire, j'aimerais que la error
pour avoir un signe positif, si la distance la plus courte entre les en-têtes implique d'aller autour dans le sens antihoraire, j'aimerais que la error
pour avoir un signe négatif.
Quelques exemples d'entrées/sorties
initial
-- final
-- error
0 .................... 30 .......... 30
30 .................... 0 .......... -30
360 .................... 1 .......... 1
1 .................... 360 .......... -1
Code:
/// <summary>
/// Calculate the error from a given initial heading to a final heading
/// </summary>
/// <param name="inital"></param>
/// <param name="final"></param>
/// <returns></returns>
private double GetHeadingError(double initial, double final)
{
double directionA = final - initial;
double directionB = 360 - (final + initial);
double error = 0;
if (Math.Abs(directionA) < Math.Abs(directionB))
{
error = directionA;
}
else
{
error = directionB;
}
return error;
}
La solution
Éditer: Ajout de vérification du moment où la différence est exactement de 180 degrés. Auparavant, cela retournait 180 ou -180 selon que la finale était plus grande ou inférieure à l'initiale. Je l'ai modifié pour qu'il revienne positif 180 dans les deux cas.
Alors voici ma tentative ...
private static double GetHeadingError(double initial, double final)
{
if (initial > 360 || initial < 0 || final > 360 || final < 0)
{
//throw some error
}
var diff = final - initial;
var absDiff = Math.Abs(diff);
if (absDiff <= 180)
{
//Edit 1:27pm
return absDiff == 180 ? absDiff : diff;
}
else if (final > initial)
{
return absDiff - 360;
}
else
{
return 360 - absDiff;
}
}
Autres conseils
Si je comprends correctement à la question, je pense que le code suivant devrait fonctionner:
private double GetHeadingError(double initial, double final)
{
if(initial == 360) initial = 0;
if(final == 360) final = 0;
double clockWise = (final - initial);
double counterClockWise = (360 - final + initial);
return (Math.Abs(clockWise) <= Math.Abs(counterClockWise)) ? clockWise : -counterClockWise;
}
En gros je suis le traitement de 360 degrés la même chose que 0, je crois que c'est ok.Ce code va produire les mêmes résultats figurant dans le tableau ci-dessus.Le Code ne fait pas de vérification des limites, il s'attend à des valeurs entre 0 et 360.
Je pense que votre tableau des résultats souhaités est incorrect. Voici ma manière klunky:
private double MyGetHeadingError(double initial, double final)
{
initial += 1000;
final += 1000;
bool flipped = false;
if (initial > final)
{
double temp;
temp = final;
final = initial;
initial = temp;
flipped = true;
}
double error;
if (final - initial > 180)
final = final - 360;
error = final - initial;
if (flipped == true)
error = -error;
return error;
}
Degree_Diff = (MIN(ABS(ENDCOMPASS-STARTCOMPASS),ABS(360-ENDCOMPASS+STARTCOMPASS),ABS(360-STARTCOMPASS+ENDCOMPASS)))
Voici une solution simple, bien que nommée un peu différemment et en fléchette. Basé sur Cette réponse avionique.
/// The difference of two headings in degrees such that it is always in the range
/// (-180, 180]. A negative number indicates [h2] is to the left of [h1].
double headingDiff(double h1, double h2) {
double left = h1 - h2;
double right = h2 - h1;
if (left < 0) left += 360;
if (right < 0) right += 360;
return left < right ? -left : right;
}
Edit: il y a une réponse encore plus concise ici, mais je ne l'ai pas essayé moi-même:
double headingDiff(double h1, double h2) => (h2 - h1 + 540) % 360 - 180;