Laden...

Zwei Kreise durch eine Linie verbinden

Erstellt von flacker vor 9 Jahren Letzter Beitrag vor 9 Jahren 2.654 Views
Hinweis von herbivore vor 9 Jahren

Abgeteilt von Text in einer gefüllten Ellipse darstellen, da es sich - wie auch selbst geschrieben - um ein anderes Problem handelt.

F
flacker Themenstarter:in
33 Beiträge seit 2014
vor 9 Jahren

Hallo,

leider ist nun ein anderes Problem aufgetreten. Die erstellten Kreise möchte ich nun durch eine Linie miteinander verbinden... Ich hatte es erst so gelöst, dass ich einfach eine Linie vom einen Kreismittelpunkt zum anderen Kreismittelpunkt ziehe. Nun möchte ich das jedoch ändern und zwar so, dass die Linie von der Kreisgrenze zur Kreisgrenze gezogen wird.

Mein erster Ansatz:

Gerade vom Kreismittelpunkt zum Kreismittelpunkt aufstellen. Schnittpunkte der Gerade mit beiden Kreisen berechnen. Gerade aus den beiden Schnittpunkten generieren. Dies klappt soweit, jedoch tritt der Fall auf das der Anstieg m = unendlich ist, da durch 0 geteilt wird(wenn die Gerade Horizontal ist). Damit fällt die Variante wohl flach....

Würde mich über Tipps sehr freuen.

49.485 Beiträge seit 2005
vor 9 Jahren

Hallo flacker,

den Fall, bei dem durch 0 geteilt werden müsste, könntest du leicht abfragen und separat behandeln.

herbivore

F
flacker Themenstarter:in
33 Beiträge seit 2014
vor 9 Jahren

An für sich klappt es auch, nur werden die Verbindungen teilweise an den falschen Kreisseiten angezeigt und gehen dadurch teilweise durch den Kreis hindurch, was ja eigentlich nicht sein dürfte...

Entweder habe ich etwas nicht bedacht oder falsch gerechnet, wobei ich letzteres fast ausschließen kann.(Da ich jeden Schritt nachgerechnet habe und keinen Fehler dort sehe)

5.658 Beiträge seit 2006
vor 9 Jahren

Hi flacker,

Entweder habe ich etwas nicht bedacht oder falsch gerechnet

Klingt sehr wahrscheinlich. Aber wie sollen wir dir dabei helfen, wenn du uns nicht mitteilst, wie du die Berechnung vornimmst?

Christian

Weeks of programming can save you hours of planning

C
2.122 Beiträge seit 2010
vor 9 Jahren

Ich würde sowas nicht mit Steigungen berechnen sondern mit Vektoren. Die Verbindung der Kreismitten kannst du statt mit m auch mit dem Paar abstand_x und abstand_y berechnen, das den Vektor von einem Kreismittelpunkt zum anderen darstellt.
Davon ziehst du an beiden Enden soviel ab wie dem Radius der Kreise entspricht.
Oder du berechnest aus diesem Vektor den Winkel und kannst dann mit dem von jedem Kreismittelpunkt den Verbindungspunkt auf dem Kreis berechnen, die verbindest du dann miteinander.

Mit diesem Verfahren hast du keine Spezialfälle.

F
flacker Themenstarter:in
33 Beiträge seit 2014
vor 9 Jahren

Da habt ihr auch wieder recht. Deswegen hier der Code!


                    GraphicEllipse ellipse1 = liste.GetValue(countery) as GraphicEllipse;
                    GraphicEllipse ellipse2 = liste.GetValue(counterx) as GraphicEllipse;
                    double anstieg;
                    double pluswert;

                    //Spezialfälle beachten.  x = x und y = y
                    if ((ellipse1.IX - ellipse2.IX) != 0)
                    {
                        if((ellipse1.IY- ellipse2.IY) != 0)
                        {
                            anstieg=1;
                        }

                        //Normale Berechnung des Anstiegs, falls kein Spezialfall auftritt
                        anstieg = (ellipse1.IY - ellipse2.IY) / (ellipse1.IX - ellipse2.IX);                        
                    }
                    else
                    {
                        anstieg = 0;
                    }

                    //Berechnung von n
                    pluswert = ellipse1.IY - (ellipse1.IX * anstieg);

                    //Berechnung des ersten möglichen Schnittpunktes
                    double schnittpunktXEllipse1;
                    schnittpunktXEllipse1 = (ellipse1.IX + 50) + (50 * Math.Cos(anstieg));

                    double schnittpunktYEllipse1;
                    schnittpunktYEllipse1 = (ellipse1.IY + 50) + (50 * Math.Sin(anstieg));

                    //Nur ein Test, ob der ermittelte Punkt auch auf der Geraden liegt welche man oben ermittelt hat, 
                    //was komischerweise nie der Fall ist. Deswegen wurde eine Spanne von 10 eingeführt. 
                    //Liegt er innerhalb von 10, wird der Punkt benutzt(Ich denke hier könnte der Fehler sein, da die ermittelten Punkte nie auf der Gerade liegen!)
                    double vergleich = schnittpunktYEllipse1 + (anstieg * schnittpunktXEllipse1) + pluswert;
                    if (vergleich > 10)
                    {
                        //Da es immer mehrere Schnittpunkte gibt(Sekante), wird wenn der erste Schnittpunkt nicht geeignet ist, der zweite berechnet. 
                        schnittpunktXEllipse1 = (ellipse1.IX + 50) - (50 * Math.Cos(anstieg));
                        schnittpunktYEllipse1 = (ellipse1.IY + 50) - (50 * Math.Sin(anstieg));
                    }


                    //Schnittpunkt mit der zweiten Ellipse berechnen, selbe Vorgehensweise wie bei der ersten Ellipse
                    double schnittpunktXEllipse2;
                    schnittpunktXEllipse2 = (ellipse2.IX + 50) + (50 * Math.Cos(anstieg));

                    double schnittpunktYEllipse2;
                    schnittpunktYEllipse2 = (ellipse2.IY + 50) + (50 * Math.Sin(anstieg));

                    vergleich = schnittpunktYEllipse2 + (anstieg * schnittpunktXEllipse2) + pluswert;
                    if (vergleich > 10)
                    {
                        schnittpunktXEllipse2 = (ellipse2.IX + 50) - (50 * Math.Cos(anstieg));
                        schnittpunktYEllipse2 = (ellipse2.IY + 50) - (50 * Math.Sin(anstieg));
                    }

Ich habe versucht das Ganze zu kommentieren, damit ihr schneller reinkommt. Sind irgendwelche Dinge unklar, einfach Fragen.

5.658 Beiträge seit 2006
vor 9 Jahren

Hi flacker,

nimms mir nicht übel, aber für mich ist der Quelltext wenig nachvollziehbar. Schon die erste if-Abfrage sieht nicht gut durchdacht (oder getestet) aus, oder es fehlt einfach noch ein else. Du erklärst auch nicht, woher der konstante Faktor von 50 kommt, mit dem du die Ergebnisse berechnest.

Daher mein Tip: Teste und Debugge deinen Code mit den Hilfsmitteln, die du zur Verfügung hast. Nur so kannst du wirklich nachvollziehen, was passiert und sicherstellen, daß wirklich alle Fälle korrekt behandelt werden.

Christian

Weeks of programming can save you hours of planning

F
flacker Themenstarter:in
33 Beiträge seit 2014
vor 9 Jahren

Ja da hast du Recht, deswegen hab ich auch versucht das Problem zu erklären. Die Konstante von 50 muss ich noch durch eine Variable ersetzen. 50 = Radius des Kreises.

Ich debugge schon seit tage durch und rechne die Ergebnisse nach. Ich werde mal die Variablen umbenennen um das ganze vielleicht verständlicher zu machen.

F
flacker Themenstarter:in
33 Beiträge seit 2014
vor 9 Jahren

Durch deine Hinweis nochmal zu debuggen, habe ich nochmal alles auf Papier mitgerechnet und habe dadurch den Fehler gefunden. Danke nochmal.

Auch wenn man es mehrmals debuggt hat, manchmal hilft noch ein weiteres mal^^

49.485 Beiträge seit 2005
vor 9 Jahren

Hallo flacker,

ich finde die Berechnung unnötig kompliziert und würde den Vorschlag von chilic vorziehen:

int r1;
int x1;
int y1;

int r2;
int x2;
int y2;

protected void DoPaint (Object sender, PaintEventArgs e)
{
   e.Graphics.DrawEllipse (Pens.Blue,  x1-r1, y1-r1, 2*r1, 2*r1);
   e.Graphics.DrawEllipse (Pens.Green, x2-r2, y2-r2, 2*r2, 2*r2);

   int deltaX = x2-x1;
   int deltaY = y2-y1;
   int length = (int)Math.Round (Math.Sqrt (deltaX*deltaX + deltaY*deltaY));

   if (length - r1 - r2 <= 0) { return; }

   int x11 = x1 + (deltaX * r1 / length);
   int y11 = y1 + (deltaY * r1 / length);
   int x22 = x2 - (deltaX * r2 / length);
   int y22 = y2 - (deltaY * r2 / length);

   e.Graphics.DrawLine (Pens.Red, x11, y11, x22, y22);
}

Möglicherweise gibt es durch die Integer-Arithmetik Rundungsfehler im Bereich von einem Pixel, aber vom Prinzip her sollte es stimmen.

Beim Erstellen des Codes bin ich davon ausgegangen, dass alle sechs Ausgangswerte positiv sind und habe nur dafür getestet.

herbivore

F
flacker Themenstarter:in
33 Beiträge seit 2014
vor 9 Jahren

Ja! Es war wirklich zu Kompliziert. Ich weiß nicht ob es zufall ist aber ich habe gestern das Ganze nochmal umgeschrieben und zwar genau so wie du es eben gepostet hast^^ und seit gestern klappt es auch ohne Probleme(also nicht kopiert sondern selber geschrieben ohne deine Antwort gesehen zu haben)