AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Benötige Hilfe von einen Mathematiker
Thema durchsuchen
Ansicht
Themen-Optionen

Benötige Hilfe von einen Mathematiker

Ein Thema von EWeiss · begonnen am 16. Dez 2008 · letzter Beitrag vom 17. Dez 2008
 
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#17

Re: Benötige Hilfe von einen Mathematiker

  Alt 17. Dez 2008, 08:27
Okay, ich poste dann mal den momentanen Code:
Code:
public partial class Form1 : Form
    {
        float margin = 30; // Abstand Ellipse <> Button
        float distance = 50; // Abstand Button <> Button
        double start_angle = 1.15 * Math.PI; // Startwinkel im Bogenmaß, hier so "links unten"
        double end_angle = 1.75 * Math.PI; // Endwinkel, hier ~ "unten rechts"

        List<RadioButton> buttons;

        public Form1()
        {
            InitializeComponent();

            buttons = new List<RadioButton>();
            buttons.Add(radioButton1);
            button1_Click(null, null);
            button1_Click(null, null);
        }

        private float sqr(float a)
        { return a * a; }

        private float Abstand(PointF p1, PointF p2)
        {
            return (float)Math.Sqrt(sqr(p1.X - p2.X) + sqr(p1.Y - p2.Y));
        }

        private PointF GetPoint(float a, float b, double phi)
        {
            return new PointF((float)(a * Math.Cos(phi)), (float)(b * Math.Sin(phi)));
        }

        private double GetNewPhi(float a, float b, double oldphi, double arc)
        {
            double step = 0.005;

            double result = oldphi;

            PointF old = GetPoint(a, b, oldphi);

            do
            {
                result += step;
            }
            while (Abstand(old, GetPoint(a, b, result)) < arc);

            return result;
        }

        private Point PointToKoord(float a, float b, double phi, float margin)
        {
            PointF Res = GetPoint(a + margin, b + margin, phi);

            Res.Y = -Res.Y; // Y-Achse umkehren

            Res.X += a;
            Res.Y += (pictureBox1.Height - b);

            Res.X += pictureBox1.Left;
            Res.Y += pictureBox1.Top;

            Res.X -= radioButton1.Width / 2;
            Res.Y -= radioButton1.Height / 2;

            return new Point((int)Res.X, (int)Res.Y);
        }

        private void pictureBox1_SizeChanged(object sender, EventArgs e)
        {
            float hratio = (240f / 293) * pictureBox1.Height / pictureBox1.Width;
            float a = pictureBox1.Width / 2f;
            float b = a * hratio;

            double phi = start_angle;

            foreach (RadioButton elem in buttons)
                elem.Visible = false;

            for(int i = 0; i < buttons.Count; i++)
            {
                buttons[i].Visible = true;
                buttons[i].Location = PointToKoord(a, b, phi, margin);

                phi = GetNewPhi(a, b, phi, distance);

                if (phi > end_angle)
                    break;
            }

        }
Wie du siehst, kängt da noch ein kleiner Rattenschwanz an Funktionen dran, damit es etwas einfacher wird.

Mal kurz alles erklärt:

Allgemein
a und b beschreiben die Ellipse. Siehe auch Wikipedia (Die beiden Achsenabschnitte: a ist horizontal, b ist vertikal).

Der Winkel in der Ellipse beschreibt dann einen Punkt. Der Koordinatenursprung hierfür ist der Ellipsenmittelpunkt. Der Winkel fängt nach rechts mit 0 an und ist positiv gegen den Uhrzeigersinn. Er wird im Bpgenmaß gezählt.
D.h. ein Wert von PI entspricht "links" und ein Wert von 1.5 * Pi entspricht "unten".

sqr()
Quadriert das Argument.

Abstand()
Berechnet den Abstand zwischen 2 Punkten mit Pythagoras.

GetPoint()
Rechnet die Koordinaten um.
Die Parameter a und b beschreiben die Ellipse, der Winkel phi beschreibt dann einen Punkt auf der Ellipse. Die Funktion gibt dann den Punkt in kartesischen Koordinatren zurück. (hier zeigt die y-Achse noch nach oben, beim debuggen nicht wundern)

GetNewPhi
Das ist die iterative Berechnung von Phi. Es wird sozusagen solange der Winkel ein Stückchen erhöähtr, bis der gegebene Anstand erreicht (= etwas überschritten) wurde.

GetNewPhi berechnet allerdings der Geschwindigkeit wegen den Abstand mit dem Pythagoras, was aber falsch ist. Korrekt wäre, alle infinitesimalen Abstände zu integrieren. Wenn die Ellipse aber nicht gerade ein Verhältnis von 10:1 hat, ist das eine akzeptable Näherung.
(Näherung wird schlechter, wenn der Abstand größer wird, oder die Ellipse "platter")

PointToKoord
Rechnet die Koordinaten um, machst also aus einem Punkt auf der Ellipse die Position für den Radiobutton.

Zuerst wird die Position ind kartesische Koordinaten umgewandelt, dann muss die Y-Achse umgedreht werdern. (Da bei uns ja Y nach unten größer wird.)
Anschließend muss man noch die Koordinaten (Die ja relativ zum Ellipsenmitelpunkt sind) relativ zum Formular machen.

SizeChanged
Hier werden die Buttons neu arrangiert. a und b müssen berechnet werden (Beschreiben ja die Ellipse die auf dem Bild zu sehen ist)

In jedem Schritt wird dann ein Radiobutton angeordnet, und der Winkel für den nächsten berechnet. Sollte dieser über dem endwinkel liegen, wird abgebrochen

Wieviele Radiobuttons in den Bereich passen, kann man vorher leider nicht genau sagen.

Falls du noch Fragen hast, frag

Grüße,
Julius
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:03 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz