Entwickler-Ecke

WinForms - Mittelpunkt eines Kreises


YK18415 - Mo 09.01.17 15:33
Titel: Mittelpunkt eines Kreises
Hallo,

Ich habe einen Kreis, der die Eigenschaften X,Y,Radius,Width,Height,Kmx und Kmy hat.
X und Y stellt den oberen linken Punkt eines Rechteckes dar, das den Kreis beim Zeichnen umschließt. Von dem Punkt aus hat der Kreis (bzw. das umschließende Rechteck) die Breite "Width" und die Höhe "Height". Den Radius berechnete ich indem ich einfach den Durchmesser (Width) geteilt durch 2 nahm.

Radius-Code:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
        public double Radius
        {
            get
            {
                return width / 2;
            }

            set
            {
                Height = value * 2;
                Width = value * 2;
            }
        }

Den Mittelpunkt des Kreises berechnete ich mit den Koordinaten X und Y. Ich addierte dann den Radius (ist ja die Hälfte des Durchmessers, also müsste es ja klappten) zu den X- und Y-Koordinaten hinzu.

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
        public double Kmx
        {
            get
            {
                return X + Radius;
                //return X + width / 2;
            }

            set
            {
                //kmy = X + value;
                kmx = value;
            }
        }

        public double Kmy
        {
            get
            {
                return Y + Radius;
                //return Y + height / 2; 
            }

            set
            {
               
                //kmy = Y + value;
                kmy = value; 
            }
        }

Auch wenn ich den Code in den Kommentaren benutze, sieht es gleich aus.

Ist das richtig oder sollte man eine Kreismittelpunkt ganz anders gestalten?

Gruß

PS: Irgendwie bin ich zu blöd C#-Tags hinzuzufügen... :( Das macht man wie genau? :(

Moderiert von user profile iconTh69: C#-Tags hinzugefügt

Moderiert von user profile iconTh69: Beiträge zusammengefasst


Th69 - Mo 09.01.17 15:54

Hallo,

mir kommt eigenartig vor, daß dein Getter und Setter bei Kmx und Kmy nicht synchron sind (d.h. du setzt kmx, gibst aber im Getter etwas anderes zurück).

PS: Für C#-Tags einfach Code markieren und unter "Bereiche" auf das "+"-Symbol klicken oder aber per Hand

Quelltext
1:
[cs]C# Code...[/cs]                    


YK18415 - Mo 09.01.17 16:15

Hallo Th69,

was sollte ich denn lieber im Getter zurückgeben? Ich muss ja irgendwie sagen, wo die X-Koordinate des Mittelpunktes ist und da fiel mir nur das ein, was ich da stehen habe... :/ Entsprechend auch für die Y-Koordinate.

Und danke für die Erklärung! :)


Th69 - Mo 09.01.17 16:38

Die Frage ist eher: soll es den Setter dann überhaupt geben und wenn ja, dann sollte doch beim Setzen und danach wieder auslesen der gesetzte Wert rauskommen, oder?

C#-Quelltext
1:
2:
Kmx = 42;
Assert.AreEqual(Kmx, 42);


YK18415 - Mo 09.01.17 17:13

Ja genau, dieser Wert soll dann herauskommen.
Ich habe viel herumprobiert und meistens sieht es immer so aus (siehe Anhang). Die obere linke Ecke des Rechteckes soll der errechnete Mittelpunkt sein. Sieht ja zumindest passend aus...

Was genau meinst du mit deinem Code? Du schaust, ob die Werte gleich sind?


Th69 - Mo 09.01.17 17:30

Ja, das ist ein Unit Test, s.a. Creating Unit tests for your c# code [https://www.codeproject.com/Articles/391465/Creating-Unit-tests-for-your-csharp-code]
So kannst du dann deinen Code gut (und schnell) testen.

Ich würde erwarten, daß du bei einem Kreis als Grundeigenschaften MX,MY und Radius als Grundeigenschaften hast und die anderen Eigenschaften sich komplett draus berechnen (und setzen) lassen.
Bedenke aber auch das Kreis-Ellipse-Problem [https://de.wikipedia.org/wiki/Kreis-Ellipse-Problem], insb. wenn man sowohl Width als auch Height setzen kann.


YK18415 - Mo 09.01.17 17:42

Also statt den Mittelpunk aus X und Y zu berechnen, meinst du, ich sollte lieber den Mittelpunkt am Anfang irgendwie berechnen und daraus dann X und Y?


Th69 - Mo 09.01.17 19:08

Wie sehen denn die Konstruktoren dieser Klasse aus, d.h. mit welchen Werten initialisierst du einen Kreis und welche Member hat diese Klasse (bis jetzt sehe ich width und kmx / kmy - wobei du die beiden letzteren ja bisher nur setzt)?


Delete - Mo 09.01.17 19:12

- Nachträglich durch die Entwickler-Ecke gelöscht -


YK18415 - Di 10.01.17 09:30

Wenn ich auf einen button klicke, habe ich diesen Code:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
 for (int i = 0; i < RndNumber2; i++)
            {
                int rndnumber1 = Rnd.Next(01600);
                Asteroid asteroids = new Asteroid() { X = rndnumber1, Radius = (int)numericUpDown1.Value };
                listBox1.Items.Add(asteroids);
                pictureBox1.Refresh();
            }


Y soll am Anfang 0 sein (Oben an der pictureBox). Den Radius füge ich zur Laufzeit hinzu.




@Frühlingsrolle: Also X und Y komplett weglassen und dafür kmx und kmy benutzen?


Delete - Di 10.01.17 09:43

- Nachträglich durch die Entwickler-Ecke gelöscht -


Christian S. - Di 10.01.17 09:58

Es macht keinen Sinn, die Information, wo der Kreis sich befindet, redundant zu speichern und dann Aufwand zu betreiben, dass auch beide Speicher synchron sind. Ich würde intern eine Information speichern und daraus beide veröffentlichten Eigenschaften berechnen.


Delete - Di 10.01.17 10:10

- Nachträglich durch die Entwickler-Ecke gelöscht -


YK18415 - Di 10.01.17 10:48

@Frühlingsrollen: Soweit verstehe ich das, nur habe ich zwei Probleme:

1. Wenn ich dem Rechteck neue Werte zuweise, dann sagt er, dass es kein Kontruktor mit zwei Argumenten gibt... Liegt das daran, dass ich schon woanders eins zeichne mit einer anderen Syntax?
2. Wenn ich die obere linke Ecke haben möchte, müsste es denn nicht lauten:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
  public Point Position
        {
            get
            {
                return position;
            }

            set
            {
                position = value;
                mittelpunkt.X = position.X - (int)Radius;
                mittelpunkt.Y = position.Y - (int)Radius;
            }

?


YK18415 - Di 10.01.17 11:27

Ach neee... ^^ die zweite Frage hat sich erledigt. :)


Delete - Di 10.01.17 11:36

- Nachträglich durch die Entwickler-Ecke gelöscht -


YK18415 - Di 10.01.17 12:19

Also ich hatte das bisher so, dass ich bei der Initialisierung in den runden Klammern nichts stehe hatte und die Werte anschließend in die geschweiften Klammern schrieb.
Ist das grundlegend falsch? Weil das hatte eig. immer geklappt.


Delete - Di 10.01.17 12:38

- Nachträglich durch die Entwickler-Ecke gelöscht -


Christian S. - Di 10.01.17 13:34

Nein, das ist nicht nur eine andere Darstellung.

Wenn ich das hier mache:

C#-Quelltext
1:
2:
3:
MeineKlasse test = new MeineKlasse() {
  Foo = "bar";
};


ist das äquivalent zu:

C#-Quelltext
1:
2:
MeineKlasse test = new MeineKlasse();
MeineKlasse.Foo = "bar";


Es wird weiterhin ein parameterloser Konstruktor aufgerufen, das heißt das Setzen der Property passiert nach jedem Initialisierungscode.

Wenn ich das hier mache

C#-Quelltext
1:
MeineKlasse test = new MeineKlasse("bar");                    

habe ich einen Konstruktor mit einem Parameter, der anhand dieses Parameters Initialisierungen ausführen kann.


YK18415 - Di 10.01.17 17:15

Ahhh, gut mal den Unterschied zu wissen @Christian S. :)


Wenn ich nun den Mttelpunkt habe und ich schauen möchte welchen Abstand dieser zu einem Rechteckspunkt hat, dann hilft es doch, den einen Punkt in den Koordinatenursprung zu "verschieben", richtig? Das heißt ich nehme "die Koordinaten von einem Punkt minus die Koordinaten vom anderen Punkt" und wende dann den Pythagoras an.

Woher weiß ich aber, welche Koordinaten ich von welchen abziehen muss? Ich meine, um zu schauen, ob der Kreis den oberen linken Rand eines Rechteckes berüht, ist ja noch ok. da weiß ich, wenn der kreis oberhalb des Rechteckes ist, dann muss ich Rechteck X/Y - Kreis X/Y (Mittelpunkt) rechnen.

Aber was mache ich wenn der kreis unterhalb des Rechteckes liegt?


Delete - Di 10.01.17 18:24

- Nachträglich durch die Entwickler-Ecke gelöscht -


Ralf Jansen - Di 10.01.17 19:27

Es ändert sich nur das Vorzeichen. Und jetzt überleg nochmal wie wichtig beim Satz des Pythagoras das Vorzeichen der beteiligten Seiten sind um die Länge der dritten Seite zu berechnen.


YK18415 - Mi 11.01.17 10:53

Stimmt, dann sind die Vorzeichen egal.
Naja, ich möchte ja schauen, ob der Abstand zwischen Kreismittelpunkt und Rechtecksecke kleiner als der Radius ist...

Bei der oberen rechten Ecke habe ich folgendes:

C#-Quelltext
1:
2:
3:
double xe1 = this.X - otherObject.X;
double ye1 = this.Y - otherObject.Y;
double ae1 = Math.Sqrt(Math.Pow(xe1, 2) + Math.Pow(ye1, 2));

otherObject ist mein Kreis.

Aber das ist doch nicht der gängige Weg?

Gruß

Moderiert von user profile iconTh69: C#-Tags hinzugefügt


Ralf Jansen - Mi 11.01.17 11:04

Der gängige Weg für was?


YK18415 - Mi 11.01.17 11:08

Der gängige Weg für so eine Kollisionsabfrage.

Irgendetwas scheine ich falsch zu machen, da er mir eine Kollision anzeigt, obwohl mein Kreis noch nicht im Rechteckspunkt liegt...


Ralf Jansen - Mi 11.01.17 12:06

Dort wo man Kollisionsabfragen üblicherweise macht hat man vermutlich nie echte Kreise sondern Polygone. Für den Test ob sich ein Punkt in einem Polygon befindet gibt es sicher schnelleres als Pythagoras.

Dein Code zur Abstandsberechnung sieht richtig aus. Ein Kreis und ein Rechteck könne sich aber schneiden ohne das eine Ecke im Kreis ist. Ob das dein Problem ist oder ein anderes kann ich nicht sagen dafür ist mir der Inhalt dieses Threads zu Wirr um tatsächlich zu helfen.


Delete - Mi 11.01.17 19:02

- Nachträglich durch die Entwickler-Ecke gelöscht -