Konvertierung von Polarkoordinaten in Rechteckkoordinaten

4003
mjcopple

Dies ist leistungskritisch. Ich habe gemessen und festgestellt, dass die sqrtVerwendung der cosMethode schneller ist als die Methode.

Mir ist bewusst, dass dieser Code nur für einige Punkte funktioniert, daher ist dies kein Problem.

Pointist System.Drawing.Point. _offsetist auch vom Typ Point.

Ich nahm an, und der Profiler schien zu bestätigen, dass try/ catchden Code nicht verlangsamt, wenn keine Ausnahme auftritt. Bitte korrigieren Sie mich, falls das falsch ist.

/// <summary>
/// Convert from polar coordinates to rectangular coordinates.
/// Only works for points to the left of the origin.
/// </summary>
/// <param name="radius">The radius of the point in pixels.</param>
/// <param name="theta">The angle of the point in radians.</param>
/// <returns>The point in rectangular coordinates.</returns>
internal Point PolarToRectangular(
        double radius,
        double theta)
{
    try
    {
        double sin = Math.Sin(theta);

        // This is faster then:
        // double cos = Math.Cos(theta);
        double cos = -Math.Sqrt(1 - (sin * sin));

        Int32 x = _offset.X + (Int32)Math.Round(radius * cos);
        Int32 y = _offset.Y + (Int32)Math.Round(radius * sin);

        return new Point(x, y);
    }
    catch (OverflowException ex)
    {
        ex.Data.Add("Screen polar Radius", radius);
        ex.Data.Add("Screen polar Theta", theta);
        throw;
    }
}
Antworten
19

3 Antworten auf die Frage

16
Michael K

Ich würde in Betracht ziehen, eine Suchtabelle zu verwenden, um Ihre Sinus zu finden. Wie genau berechnen Sie einen Winkel? Diese Antwort auf stackoverflow enthält einige interessante Informationen zum Erstellen von Benchmarks und deren Benchmarks für zwei Dezimalstellen. Wenn Sie die volle Genauigkeit eines Doppels verwenden, wird Ihre aktuelle Methode schneller sein. Wenn Sie jedoch eine feste Genauigkeit haben, ist eine Nachschlagetabelle günstig.

Solange die Ausnahme außergewöhnlich ist (und für mich so aussieht), wird dies zu einem geringen Aufwand für Ihre Laufzeiten führen. Siehe: https://stackoverflow.com/q/52312/487663 .

12
winwaed

Ja, ich denke das wird ziemlich schnell gehen. Es kann verlockend sein, den cos calc so zu verschieben, dass er einen vollständigen Pythagoras mit dem Radius ausführt. Dies spart eine Zuweisung, erfordert aber eine zusätzliche Multiplikation (1 * 1 ist bereits in Ihrer aktuellen Version bekannt).

Als eine Frage des persönlichen Stils (möglich, weil ich in mehreren Sprachen codiere), würde ich jedoch unterschiedliche Namen für Ihre Sin- und Cos-Variablen verwenden. Die meisten Sprachen würden das nicht akzeptieren und persönlich hätte ich das Potenzial, mich zu verwirren.

3
ICR

Als völlig unerprobte Mikrooptimierung würde ich vermuten (Int32)(radius * cosTheta + 0.5), dass sie geringfügig schneller sein wird als (Int32)Math.Round(radius * cosTheta). Es wird jedoch auf 0,5 aufgerundet statt aufgerundet, was möglicherweise nicht das ist, was Sie wollen.