myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Grundlagen von C# » Berechnung von Schnittpunkten auf 2 Geraden des Polygons
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Berechnung von Schnittpunkten auf 2 Geraden des Polygons

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
Garzec Garzec ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2016
Beiträge: 50
Entwicklungsumgebung: Visual Studio
Herkunft: Gießen / Hessen


Garzec ist offline

Berechnung von Schnittpunkten auf 2 Geraden des Polygons

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo smile

ich versuche den Schnittpunkt von zwei Geraden zu berechnen. Benötigen tue ich das für eine Berechnung einer Fläche eines zufällig generierten Polygons. Mir geht es hierbei aber erstmal nur um die Schnittpunktberechnung. Momentan sieht diese so aus:

C#-Code:
private void SchnittpunktBerechnung(int startIndex1, int startIndex2)
        {
            //Strecke AB = Punkt1 + s * (Punkt2 - Punkt1)
            //Strecke CD = Punkt3 + t * (Punkt4 - Punkt3)

            int endeIndex1 = startIndex1 + 1;
            int endeIndex2 = startIndex2 + 1;

            Point start1 = punktListe[startIndex1];
            Point ende1 = punktListe[endeIndex1];
            Point start2 = punktListe[startIndex2];
            Point ende2 = punktListe[endeIndex2];

            // Streckenfarben

            Color farbe1 = farbenListe[startIndex1];
            Color farbe2 = farbenListe[startIndex2];

            // Punkte

            int x1 = start1.X;      //Punkt1 X
            int x2 = ende1.X;       //Punkt2 X
            int x3 = start2.X;      //Punkt3 X
            int x4 = ende2.X;       //Punkt4 X

            int y1 = start1.Y;      //Punkt1 Y
            int y2 = ende1.Y;       //Punkt2 Y
            int y3 = start2.Y;      //Punkt3 Y
            int y4 = ende2.Y;       //Punkt4 Y

            // Konstanten

            int mx = x2 - x1;
            int nx = x3 - x4;  //x4 - x3;
            int ox = x3 - x4;  //x3 - x1;

            int my = y2 - y1;
            int ny = y3 - y4;  //y4 - y3;
            int oy = y3 - y4;  //y3 - y1;

            // Determinanten

            int d1 = mx * ny - my * nx;
            int d2 = ox * ny - oy * nx;
            int d3 = mx * oy - my * ox;

            // Fallunterscheidung

            if (d1 == d2 && d1 == d3 && d1 == 0)
            {
                Console.WriteLine("Strecken liegen aufeinander");    //------- TEST
            }
            else if (d1 == 0 && d2 != 0 && d3 != 0)
            {
                Console.WriteLine("kein Schnittpunkt");    //------- TEST
            }
            else if (d1 != 0)
            {
                Console.WriteLine("Schnittpunkt");    //------- TEST
            }

            // s und t

            double s = 1F * d2 / d1;
            double t = 1F * d3 / d1;

            // Überprüfung s und t

            Console.WriteLine("Strecke: " + farbe1 + "Strecke: " + farbe2);    //------- TEST

            if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
            {
                Console.WriteLine("Schnittpunkt auf den Strecken");    //------- TEST
            }
            else
            {
                Console.WriteLine("Schnittpunkt auf den Geraden aber nicht auf den Strecken");    //------- TEST
            }

            // Schnittpunktberechnung

            int sx = Round(x1 + s * (x2 - x1));
            int sy = Round(y1 + s * (y2 - y1));

            // Schnittpunkt

            Point schnittPunkt = new Point(sx, sy);

            Console.WriteLine(schnittPunkt);    //------- TEST

            Console.WriteLine("s: " + s + " t: " + t);

            Console.WriteLine("************************************************************");    //------- TEST
        }

Das Problem an der Sache ist, das bei meiner Testroutine immer s=0 und t=1 ist. Und das Problem liegt wohl oben bei den Konstanten. Rechts auskommentiert habe ich meine vorherige Berechnung, diese stimmte aber auch nicht ganz. Kennt ein Mathe-Ass die richtige Rechnung? Zunge raus
02.05.2016 10:40 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.998
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
C#-Code:
int mx = x2 - x1;
int nx = x3 - x4;  //x4 - x3;
int ox = x3 - x4;  //x3 - x1;

int my = y2 - y1;
int ny = y3 - y4;  //y4 - y3;
int oy = y3 - y4;  //y3 - y1;

Bisschen komisch, nicht? Copy&Paste ist NICHT dein Freund.

LaTino
02.05.2016 12:09 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Garzec Garzec ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2016
Beiträge: 50
Entwicklungsumgebung: Visual Studio
Herkunft: Gießen / Hessen

Themenstarter Thema begonnen von Garzec

Garzec ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Das es sich bei nx und ox doppelt ist vom Abschreiben richtig, falls du das meinst.

Deswegen ja meine Frage nach dem Fehler in der Berechnung :/
02.05.2016 13:07 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.998
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich meinte nicht nur das, sondern auch, dass die Kommentare nicht dazu passen. Wenn wir das jetzt bei uns ausprobieren, sollen wir raten, was du uns sagen wolltest?

Ansonsten ist die Berechnung 1:1 so wie  hier erklärt. Wenn du nachvollziehen möchtest, wo es schief geht:  [Artikel] Debugger: Wie verwende ich den von Visual Studio? sollte dir helfen. Nur vom draufschaun wird einem bei deiner Wahl von Variablenbezeichnungen eher schwindlig, als dass man einen Fehler sieht - will sagen, letzten Endes können wir für dich auch nur debuggen, und das kannst du besser selber :).

LaTino
02.05.2016 13:15 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Garzec Garzec ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2016
Beiträge: 50
Entwicklungsumgebung: Visual Studio
Herkunft: Gießen / Hessen

Themenstarter Thema begonnen von Garzec

Garzec ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Achso sorry, ich hatte unten noch geschrieben, dass die Kommentare rechts einfach nur meine ursprüngliche "Berechnung" war. Also das, was vorher da stand.

Den Debugger hatte ich schon benutzt, daher weiß ich ja das s immer 0 ist und t immer 1. Führe ich das ganze zurück sind oben die Startberechnungen falsch.

Du hast Recht, dass ich das am Besten selber rausfinden kann, trotzdem dachte ich vielleicht erkennt jemand oben schon den Fehler.
02.05.2016 13:20 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.998
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Na, du sagst ihm doch, dass s immer null sein soll, und zwar hier:

C#-Code:
int d2 = ox * ny - oy * nx;
double s = 1F * d2 / d1;

und weil bei dir, wie ich schrieb, ox == nx und oy == ny, ist d2 immer null, und sist 0/irgendwas, was auch immer 0 ist. Deshalb nochmal die Frage, was du dort oben mit den ox, nx, oy, ny treibst.

LaTino

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von LaTino am 02.05.2016 13:24.

02.05.2016 13:24 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Garzec Garzec ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2016
Beiträge: 50
Entwicklungsumgebung: Visual Studio
Herkunft: Gießen / Hessen

Themenstarter Thema begonnen von Garzec

Garzec ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich habe meine Berechnung abgeändert, s wird jetzt auch nicht mehr 0. mx,nx,ox, .... dienen eigentlich nur als Zwischenschritte. Ich könnte unten in die Rechnung ja auch direkt die variablen eingeben, aber dann würde es denke ich zu unübersichtlich und die Berechnung zu groß/lang.

Das Ganze sieht nun so aus:

C#-Code:
            int x1 = start1.X;      //Punkt1 X
            int x2 = ende1.X;       //Punkt2 X
            int x3 = start2.X;      //Punkt3 X
            int x4 = ende2.X;       //Punkt4 X

            int y1 = start1.Y;      //Punkt1 Y
            int y2 = ende1.Y;       //Punkt2 Y
            int y3 = start2.Y;      //Punkt3 Y
            int y4 = ende2.Y;       //Punkt4 Y

            // Konstanten

            int mx = x2 - x1;
            int nx = x4 - x3;
            int ox = x3 - x1;

            int my = y2 - y1;
            int ny = y4 - y3;
            int oy = y3 - y1;

            // Determinanten

            int d1 = mx * ny - my * nx;
            int d2 = ox * ny - oy * nx;
            int d3 = mx * oy - my * ox;

            // s und t

            double s = 1F * d2 / d1;
            double t = 1F * d3 / d1;

            // Schnittpunktberechnung

            int sx = Round(x1 + s * (x2 - x1));
            int sy = Round(y1 + s * (y2 - y1));

Dennoch erkennt er die Schnittpunkte nicht richtig. Mache ich noch etwas falsch?
02.05.2016 13:53 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Palin Palin ist männlich
myCSharp.de-Mitglied

Dabei seit: 22.08.2011
Beiträge: 1.090
Entwicklungsumgebung: VB.net


Palin ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Wenn du den Schnitt 2er Graden berechnen willst. Bestimme die beiden Graden Gleichungen.

F1(x) = m1*x + b1 und F1(x) = m1*x + b2

wobei

m1 = (y2-y1) / (x2-x2)

und

b1 = y1 - m*x1

(Für F2 natürlich auch bestimmen)

Und setze diese gleich.
F1(x) = F2(x)
m1*x + b1 = m2*x +b2

=>
x = (b2-b1) / (m1 - m2)

x dann in F1 oder F1 einsetzen und den y Wert bestimmen.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Palin am 02.05.2016 14:10.

02.05.2016 14:08 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.998
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Edit, @palin: sein Algo stimmt schon^^

Rundungsfehler, 100%.

C#-Code:
int sx = Round(x1 + s * (x2 - x1));
int sy = Round(y1 + s * (y2 - y1));

Erstens ist int denkbar ungeeignet für Schnittpunkte, zweitens habe ich keine Ahnung, welches Round() du da aufrufst. Für sx/sy als float oder double liefert er mir ausreichend genaue Ergebnisse.

Du kannst deine Ergebnisse übrigens gegen Wolfram Alpha prüfen. ( Beispiel).

LaTino

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von LaTino am 02.05.2016 14:22.

02.05.2016 14:22 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Garzec Garzec ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2016
Beiträge: 50
Entwicklungsumgebung: Visual Studio
Herkunft: Gießen / Hessen

Themenstarter Thema begonnen von Garzec

Garzec ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Sorry, meine Rundungsmethode:

C#-Code:
private int Round(double d)
        {
            if (double.IsPositiveInfinity(d))
                return int.MaxValue;
            if (double.IsNegativeInfinity(d))
                return int.MinValue;
            return Convert.ToInt32(Math.Round(d, MidpointRounding.AwayFromZero));
        }
02.05.2016 14:24 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.998
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ja, wie gesagt, wenn du auf Ganzzahlen rundest, wenn gebrochene Zahlen rauskommen, musst du dich nicht wundern.

LaTino
02.05.2016 14:25 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Garzec Garzec ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2016
Beiträge: 50
Entwicklungsumgebung: Visual Studio
Herkunft: Gießen / Hessen

Themenstarter Thema begonnen von Garzec

Garzec ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Tut mir leid ich bin ein Programmieranfänger.

Der Punkt kann nur Int-Werte annehmen, wie könnte ich das Ganze umbauen das er die richtigen Werte entgegen nimmt?

Ich versuche ja schon erst am Ende zu runden.
02.05.2016 14:28 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.998
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Wenn ich willkürlich in einem Koordinatensystem vier Punkte eintrage und dann Linien zeichne, wird deren Schnittpunkt so gut wie nie genau auf einem ganzzahligen Punkt liegen...

Zitat:
Der Punkt kann nur Int-Werte annehmen.

Im Gegenteil, er nimmt nur ganz, ganz selten int-Werte an.

LaTino
EDIT: oh, warte, du willst ein Point-Struct draus machen?  PointF

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von LaTino am 02.05.2016 14:38.

02.05.2016 14:35 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Garzec Garzec ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2016
Beiträge: 50
Entwicklungsumgebung: Visual Studio
Herkunft: Gießen / Hessen

Themenstarter Thema begonnen von Garzec

Garzec ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Damit meinte ich die Parameter die man mitgeben kann,

C#-Code:
            // Schnittpunktberechnung

            int sx = Round(start1.X + s * x1);
            int sy = Round(start1.Y + s * y1);

            // Schnittpunkt

            Point schnittPunkt = new Point(sx, sy);

sx und sy müssen integer sein, bei double etc. meckert er
02.05.2016 14:58 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.998
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Klick mal auf den Link. Ich denke, soviel können wir erwarten ;).
02.05.2016 15:21 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Garzec Garzec ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2016
Beiträge: 50
Entwicklungsumgebung: Visual Studio
Herkunft: Gießen / Hessen

Themenstarter Thema begonnen von Garzec

Garzec ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Sorry dein Edit kam erst nach meiner Antwort :) bzw. hatte die Seite noch nicht neu geladen

Edit: Du hast Recht, das Runden führt zu Fehlern. Aber eigentlich habe ich dann nur vor dem

C#-Code:
Point schnittPunkt = new Point(sx, sy);

exakte Werte zu übergeben. Und da muss ichs ja irgendwie hinbekommen, dass sx und sy von Kommazahlen zu Integern übergehen =?

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Garzec am 02.05.2016 15:33.

02.05.2016 15:30 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.998
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich denke, wir drehen uns im Kreis. Ich sage dir, dass du das Ergebnis nicht in Ganzzahlen speichern kannst, du sagst, "aber irgendwie muss das doch gehen". Dann sage ich wieder, dass Schnittpunkte nunmal nicht ganzzahlig sind, und du machst eine Konvertierung nach int und wunderst dich, wieso das Ergebnis dann nicht stimmt.

Du kannst runden, abschneiden, casten - völlig egal, wenn du das Endergebnis als Ganzzahl nimmst, wird es falsch sein, weil es eben keine Ganzzahl ist.

C#-Code:
int intResult1 = (int)myFloat; //zahlen hinter dem Komma abschneiden
int intResult2 = Convert.ToInt32(myFloat); //rundet

//intResult1, intResult2 sind immer noch falsch, mit GLück in seltenen Fällen aber nicht _sehr_ falsch.

Beim programmieren musst du halt immer die Datentypen benutzen, die du brauchst, um das darzustellen, was du darstellen willst. Wenn du Kommazahlen darstellen willst, kannst du kein int (also auch kein Point) nehmen.

LaTino
EDIT: Convert.ToInt32 korrigiert

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von LaTino am 02.05.2016 15:48.

02.05.2016 15:43 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Garzec Garzec ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2016
Beiträge: 50
Entwicklungsumgebung: Visual Studio
Herkunft: Gießen / Hessen

Themenstarter Thema begonnen von Garzec

Garzec ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich habe dich schon verstanden. Meine letzte Frage zielte darauf ab, ob es dann eine Möglichkeit gibt das ganze dann anders zu lösen. Wenn ich den Schnittpunkt in 2 float Werte aufteile müsste ich damit ja weiterrechnen und diese Werte dann mit der Geraden abgleichen.
02.05.2016 15:51 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
inflames2k inflames2k ist männlich
myCSharp.de-Poweruser/ Experte

avatar-3407.gif


Dabei seit: 03.01.2010
Beiträge: 2.241
Entwicklungsumgebung: Visual Studio 2010 Express


inflames2k ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Garzec,

verwende wie angesprochen PointF, in diesem werden Koordinaten als Float-Werte eingefügt.
02.05.2016 15:59 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Garzec Garzec ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2016
Beiträge: 50
Entwicklungsumgebung: Visual Studio
Herkunft: Gießen / Hessen

Themenstarter Thema begonnen von Garzec

Garzec ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Danke,

da ich mit double rechne wollte ich die Punkte, wie von LaTino schon vorgeschlagen, weglassen, um exakte Werte zu behalten. Nebenbei habe ich noch ein bisschen gekürzt und vereinfacht.

Das Ganze sieht nun so aus:

C#-Code:
private void SchnittpunktBerechnung(int startIndex1, int startIndex2)
        {
            // Punktindex

            int endeIndex1 = startIndex1 + 1;
            int endeIndex2 = startIndex2 + 1;

            Point start1 = punktListe[startIndex1];
            Point ende1 = punktListe[endeIndex1];
            Point start2 = punktListe[startIndex2];
            Point ende2 = punktListe[endeIndex2];

            // Zwischenwerte

            int x1 = ende1.X - start1.X;
            int x2 = start2.X - ende2.X;
            int x3 = start2.X - start1.X;

            int y1 = ende1.Y - start1.Y;
            int y2 = start2.Y - ende2.Y;
            int y3 = start2.Y - start1.Y;

            // Determinanten

            int d1 = x1 * y2 - y1 * x2;
            int d2 = x3 * y2 - y3 * x2;
            int d3 = x1 * y3 - y1 * x3;

            // s und t

            double s = d2 / d1;
            double t = d3 / d1;

            // Schnittpunktberechnung

            double schnittpunktX = start1.X + s * x1;
            double schnittpunktY = start1.Y + t * y1;

            // Überprüfung

            if (s >= 0 && t <= 1)
            {
                                   //Schnittpunkt auf der Strecke
            }
        }

Dennoch kommen beim Testen nicht die gewünschten Ergebnisse raus, also Er findet nicht den exakten Schnittpunkt auf der Strecke.

Kann mir jemand sagen ob bei der Rechnung oben noch Fehler eingebaut sind? Das mathematische hier ins Programm umzuschreiben fand ich doch nicht so einfach wie gedacht großes Grinsen
03.05.2016 09:48 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
inflames2k inflames2k ist männlich
myCSharp.de-Poweruser/ Experte

avatar-3407.gif


Dabei seit: 03.01.2010
Beiträge: 2.241
Entwicklungsumgebung: Visual Studio 2010 Express


inflames2k ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Wie stark ist denn die Abweichung vom von dir berechneten Schnittpunkt?
03.05.2016 11:05 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Garzec Garzec ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2016
Beiträge: 50
Entwicklungsumgebung: Visual Studio
Herkunft: Gießen / Hessen

Themenstarter Thema begonnen von Garzec

Garzec ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Das ist immer unterschiedlich. Es wird ja abgeschnitten. Daher weichen die Punkte nicht so stark ab, aber er findet den Punkt ja dann nicht mehr auf der Strecke. Weil er ja nicht DIREKT drauf liegt, sondern ganz knapp daneben und dann findet er ihn nicht mehr. Daher erstmal meine Frage nach der Rechnung, ob diese richtig ist. Damit kann man dann ja weiterarbeiten.
03.05.2016 11:15 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
t2t t2t ist männlich
myCSharp.de-Mitglied

Dabei seit: 22.10.2007
Beiträge: 413
Entwicklungsumgebung: VS2017
Herkunft: Hamburg


t2t ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Verwende mal statt double den Datentyp decimal. Dieser hat eine höhere Genauigkeit.
03.05.2016 12:47 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Garzec Garzec ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2016
Beiträge: 50
Entwicklungsumgebung: Visual Studio
Herkunft: Gießen / Hessen

Themenstarter Thema begonnen von Garzec

Garzec ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hab :)

Jetzt noch die Rechnung korrigieren :P

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Garzec am 03.05.2016 12:54.

03.05.2016 12:54 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MarsStein MarsStein ist männlich
myCSharp.de-Poweruser/ Experte

avatar-3191.gif


Dabei seit: 27.06.2006
Beiträge: 3.155
Entwicklungsumgebung: VS 2013, MonoDevelop
Herkunft: Trier -> München


MarsStein ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

C#-Code:
            // s und t

            double s = d2 / d1;
            double t = d3 / d1;

An der Stelle ist das, was in s und t steht, wieder ein ganzzahliger Wert, weil Du in der Rechenoperation nur mit Integern (d1, d2, d3) rechnest.
Sattdessen könntest Du d1, d2, d3 direkt als double deklarieren, oder eben einen der Werte in der Berechnung auf double casten:

C#-Code:
            //-----------ENTWEDER SO------------:

            double d1 = x1 * y2 - y1 * x2;
            double d2 = x3 * y2 - y3 * x2;
            double d3 = x1 * y3 - y1 * x3;

            // s und t

            double s = d2 / d1;
            double t = d3 / d1;

            //-----------ODER SO------------:

            double s = d2 / (double)d1;
            double t = d3 / (double)d1;

Gruß, MarsStein

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von MarsStein am 03.05.2016 13:07.

03.05.2016 13:07 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.998
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Wie MarsStein schrieb - ansonsten ist deine Rechnung, soweit ich sehen kann, in Ordnung. Eine Sache noch:

Wenn du am PC mit Gleitzahlen arbeitest (besonders bei float), dann überprüft man niemals mit "==", ob zwei Werte gleich sind. Der Grund dafür liegt in der Ungenauigkeit von float. Entweder du verwendest, wie vorgeschlagen, decimal, oder du machst einen sog. Delta-Vergleich:

C#-Code:
const float DELTA = 0.001; //nach Bedarf anpassen
float float1, float2;

//berechnungen...

//Vergleich:
if(Math.Abs(float1 - float2) < DELTA) DoSomething() //wenn die Werte nah genug beinander liegen, sind sie gleich)

Das sollte man beim Arbeiten mit float IMMER machen, mit double im Hinterkopf behalten und mit decimal ignorieren ;).

LaTino
03.05.2016 13:43 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
CoLo
myCSharp.de-Mitglied

Dabei seit: 25.09.2009
Beiträge: 224


CoLo ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Float, double und decimal haben eines Gemeinsam: sie sind endliche Gleitkommazahlen. Dementsprechend sollte man denen Vertrauen.

Bei float und double wird intern im Binärzahlensystem gerechnet. Beim Darstellen ins Dezimalsystem entstehen dabei kleine Rundungsfehler. Da wir Menschen nicht binär denken, sind diese kleinen Fehler zum Teil schwer nachzuvollziehen. Beim decimal wird intern im Dezimalsystem gerechnet und ist auf Rechnungen mit Geldsystemen ausgelegt. Daher sind diese für uns Menschen wesentlich genauer und deren Rundungen entsprechen auch meist unseren Erwartungen.

Je nach Anwendung würde ich aber auch ein Delta für decimal verwenden.
03.05.2016 19:15 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Garzec Garzec ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2016
Beiträge: 50
Entwicklungsumgebung: Visual Studio
Herkunft: Gießen / Hessen

Themenstarter Thema begonnen von Garzec

Garzec ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Also ich habe nun 2 Berechnungen, wobei ich weiß das die 2. Berechnung wohl das richtige Ergebnis liefert, die 1. Methode (meine Berechnung) noch nicht.

Meine Berechnung sieht momentan so aus:

C#-Code:
private void SchnittpunktBerechnung(int startIndex1, int startIndex2)
        {
            // Punktindex

            int endeIndex1 = startIndex1 + 1;
            int endeIndex2 = startIndex2 + 1;

            Point start1 = punktListe[startIndex1];
            Point ende1 = punktListe[endeIndex1];
            Point start2 = punktListe[startIndex2];
            Point ende2 = punktListe[endeIndex2];

            // Zwischenwerte

            int x1 = ende1.X - start1.X;
            int x2 = start2.X - ende2.X;
            int x3 = start2.X - start1.X;

            int y1 = ende1.Y - start1.Y;
            int y2 = start2.Y - ende2.Y;
            int y3 = start2.Y - start1.Y;

            // Determinanten

            decimal d1 = x1 * y2 - y1 * x2;
            decimal d2 = x3 * y2 - y3 * x2;
            decimal d3 = x1 * y3 - y1 * x3;

            // s und t

            decimal s = d2 / d1;
            decimal t = d3 / d1;

            // Schnittpunktberechnung

            decimal schnittpunktX = start1.X + s * x1;
            decimal schnittpunktY = start1.Y + s * y1;

            // Überprüfung

            if (s >= 0 && t >= 0 && s <= 1 && t <= 1)
            {
                //Schnittpunkt auf der Strecke
            }
        }

Die neue Berechnung sieht wie folgt aus:

C#-Code:
private void Tausche(float start, float ende)
        {
            float helper;
            helper = start;
            start = ende;
            ende = helper;
        }

        private bool LiegtDazwischen(float value, float start, float ende)
        {
            if (start > ende)
            {
                Tausche(start, ende);
            }
            return (start <= value) && (value <= ende);
        }

        private bool PunktLiegtDazwischen(PointF schnittpunkt, PointF punkt1, PointF punkt2)
        {
            return LiegtDazwischen(schnittpunkt.X, punkt1.X, punkt2.X) && LiegtDazwischen(schnittpunkt.Y, punkt1.Y, punkt2.Y);
        }

        private bool BerechneSchnittpunkt(PointF punkt1, PointF punkt2, PointF punkt3, PointF punkt4, PointF schnittpunkt)
        {
            float mx = punkt2.X - punkt1.X;
            float nx = punkt4.X - punkt3.X;
            float ox = punkt4.X * punkt3.Y - punkt3.X * punkt4.Y;

            float my = punkt2.Y - punkt1.Y;
            float ny = punkt4.Y - punkt3.Y;
            float oy = punkt2.X * punkt1.Y - punkt1.X * punkt2.Y;

            float d1 = mx * ny - my * nx;
            float d2 = nx * oy - mx * ox;
            float d3 = ny * oy - my * ox;

            if (d1 == 0)
            {
                //parallel
                schnittpunkt.X = 0;
                schnittpunkt.Y = 0;
                return false;
            }
            else
            {
                schnittpunkt.X = d2 / d1;
                schnittpunkt.Y = d3 / d1;
                return PunktLiegtDazwischen(schnittpunkt, punkt1, punkt2) && PunktLiegtDazwischen(schnittpunkt, punkt3, punkt4);
            }
        }

Aufgerufen wird meine Methode über eine Schleife, die dann über sämtliche Punkte geht:

C#-Code:
  private void BerechneSchnittpunkte()
        {
            for (int i = 0; i < 5; i++)
            {
                for (int j = i + 2; j < 5; j++)
                {
                    SchnittpunktBerechnung(i, j);
                }
            }
        }

Würde es Sinn machen das Ganze hin zur 2. Berechnung umzubauen? Wenn ich versuche die 2. Berechnung mit 4 Methoden so abzuändern, dass diese Methode genauso wie meine Berechnung in der Schleife aufgerufen wird, dann komme ich als Anfänger sehr schnell mit den Parametern durcheinander, sodass es vorne und hinten nicht mehr stimmt.

Kann ich auch meine eigene Berechnung dahingehend abändern, dass die Methoden der 2. Berechnung greifen?
04.05.2016 15:17 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.998
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Aus meiner Sicht würde eine grundsätzliche Umstrukturierung deines Codes Sinn ergeben. Nach meinem Empfinden ist das alles noch viel zu prozedural aufgebaut, also: beide Methoden, die du gepostet hast, sind wirklich nicht gut strukturiert.

Eine Klasse für einen Fixpunkt, eine Klasse für Vektoren (inkl. Normalisierung), ein paar überladene Operatoren und eine Klasse für Geraden (Fixpunkt und Richtungsvektor). Und dann kannst du den Schnittpunkt zweier Geraden sehr viel klarer darstellen.

Wenn du das jetzt noch erweitern willst - sagen wir, auf 3D - dann sitzt du doch wieder an derselben Methode und verlierst wieder den Überblick.

Und zum Probieren, ob und welche Methode das richtige errechnet, solltest du dir mal den Komponententest-Projekttyp im Visual Studio anschaun, der ist für sowas gemacht. So, wie es jetzt ist, weisst du doch zu keiner Zeit, ob eine Änderung den gewünschten Effekt hatte oder nicht.

LaTino
04.05.2016 15:37 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Garzec Garzec ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2016
Beiträge: 50
Entwicklungsumgebung: Visual Studio
Herkunft: Gießen / Hessen

Themenstarter Thema begonnen von Garzec

Garzec ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Danke für deine Hinweise, das Thema Klassen zu erlernen, da bin ich grade dran, nebenbei wollte ich aber erst die Funktionalität des Programmes sicherstellen.

Ich nutze nun die "neue" Berechnung, und versuche die 5 Parameter bei Methodenaufruf zu übergeben. Leider kommt es da zu Fehlern. Der Code:

C#-Code:
            for (int i = 0; i < punktListe.Count; i++)
            {
                for (int j = i + 2; j < 5; j++)
                {
                    PointF schnittpunkt = new PointF();
                    BerechneSchnittpunkt(punktListe[i], punktListe[j], punktListe[i + 1], punktListe[j +       1], out schnittpunkt);
                }
            }

Ich habe 2 Schleifen genommen, da er eine Exception bei einer Schleife wirft. Der Index übersteigt das Maximum und es geht nicht weiter. Dennoch kommen bei dieser Methode noch falsche Schnittpunkte heraus, meistens sind es sogar zu viele, ich denke er erkennt manche Eckpunkte noch als Schnittpunkte.

Meine Frage:

Stimmt meine neue Berechnung immer noch nicht oder übergebe ich die Parameter einfach nur falsch?

Ich habe zum Testen eine Schnittpunktliste erstellt, lasse ich die Schnittpunkte dazu malen, gehen die Linien kreuz und quer durch das Bild, die Berechnung muss also noch falsch sein ...
09.05.2016 14:37 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.998
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Die Sache ist die - sollte da noch ein Fehler vorliegen, müssten wir uns, um ihn zu finden, durch den ziemlich unübersichtlichen Code von dir wühlen - oder hier im Forum versuchen, durch draufschauen einen eventuellen Fehler zu finden.

Das ist so nicht praktikabel ;).

Ich gebe dir mal einen Schubs in eine bessere Richtung.

C#-Code:
public class Vector
{
    private const float DELTA = 0.0001f;

    public Vector(float x, float y, bool normalize) //erstellt einen Vektor und normalisiert ihn auch gleich. Für den Fall der Fälle merken wir uns den Normalisierungsfaktor.
    {
        X = x;
        Y = y;

        NormalizationFactor = (float)Math.Sqrt(x * x + y * y);
        if (normalize && NormalizationFactor > DELTA)
        {
            X /= NormalizationFactor;
            Y /= NormalizationFactor;
        }
    }
    public Vector(Point start, Point end) : this(end.X - start.X, end.Y - start.Y, true) { }
    public Vector(Point point, bool normalize) : this(point.X, point.Y, normalize) { }

    public float NormalizationFactor { get; private set; }
    public float X { get; private set; }
    public float Y { get; private set; }

    public Vector Reverse() //falls wir mal die Richtung wechseln müssen.
    {
        return new Vector(-1 * X ,-1 * Y, true);
    }
}

public class Line //wird in Parameterform gespeichert: startpunkt + t*Richtungsvektor
{
    public Vector Direction { get; private set; }
    public Vector Startpoint { get; private set; }

    public Vector Normal //der senkrecht auf der Richtung stehende Vektor. Praktisch, wenn man einen Schnittpunkt wissen will.
    {
        get
        {
            return new Vector(-1 * Direction.Y, Direction.X, false);
        }
    }

    public Line(Point startPoint, Point endPoint)
    {
        Startpoint = new Vector(startPoint, false);
        Direction = new Vector(startPoint, endPoint);
    }

    //für Umrechnung in Koordinatenform a*x + b*y = c
    public float CoordinateA { get { return Normal.X; } }
    public float CoordinateB { get { return Normal.Y; } }
    public float CoordinateC { get { return Startpoint.X*Normal.X + Startpoint.Y*Normal.Y; } }

    public PointF Intersection(Line other)
    {
        var xs = /* Zeile selber einfügen, Wikipedia hilft. */
        var ys = /* Zeile selber einfügen, Wikipedia hilft. */
        return new PointF(xs, ys);
    }
}

Schnittpunkt:  WP - Schnittpunkt zweier Geraden
So etwas in der Art meinte ich damit, dass du deinen Code etwas organisieren solltest.

LaTino
09.05.2016 15:35 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 4 Jahre.
Der letzte Beitrag ist älter als 4 Jahre.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 03.08.2020 19:59