Hallo, ich hab hier ein Problem was mich leicht in den Wahnsinn treibt. Ich möchte mittels dem Skalarprodukt zweier Vektoren prüfen ob diese auf einer Gerade liegen. Wenn dem so ist erhalte ich als Skalarprodukt eine 1 bzw. -1 ( weil Cos(0°) bzw. Cos(180°) -> auf einer Gerade). Danach wöllte ich prüfen ob diese beiden Vektoren benachbart sind oder sich überlappen. Der Sinn hinter der Sache soll sein, dass ich aus einem Dreiecksnetz wieder die Kontur eines Polygons ermittlen will und somit doppelte bzw. überlappende Kanten eliminiere.
Nun mein Problem an der Sache ist jetzt dass es für ein Skalarprodukt von 1 einwandfrei mit folgendem Code funktioniert:
Code:
var Scalar : Double; ... Scalar := VScalar(V1,V2) / (VLength(V1)*VLength(V2)); { Stufe 1 - Liegen die beiden Kanten auf einer Linie? } If (Scalar = 1) or (Scalar = -1) then Begin ...
Ist der Wert der Variable Scalar nun aber -1, überspringt das Programm munter die If-Abfrage. Ich habe mir das ganze im Debugger mal zu Gemüte geführt und wenn ich den Ausdruck "Scalar = -1" markiere sagt er mir "Scalar = -1 = false". Das finde ich relativ interessant denn wenn ich über "Scalar" fahre erhalte ich die Aussage "Scalar = -1".
Ich verstehe leider einfach nicht warum er diese Abfrage "vermasselt" und deswegen wende ich mich hilfesuchend an euch
Was ich schon probiert habe:
Delphi/Projekt neustarten Ausdruck in allen möglichen Klammervariationen
Beim Schreiben kam mir grad noch in den Sinn, dass man einfach das Quadrat von Scalar berechnen könnte, damit würde -1 wegfallen. Dennoch finde ich das nicht die optimalste Lösung, da ich solche Probleme an anderer Stelle (if-Abfrage mit = true/false) auch bereits hatte und dort das Quadrat nicht hilft^^.
Grüße
//Edit: Ok, das mit dem Quadrat funktioniert interessanterweise auch nicht... dann schreibt er bei Scalar = 1 = false, auch wenn Scalar mittlerweile 1 ist :S.
Zuletzt geändert von TheQaa am Mi Mai 26, 2010 13:49, insgesamt 1-mal geändert.
Registriert: Di Okt 13, 2009 17:25 Beiträge: 365
Programmiersprache: C++
Hey, vielleicht liegt es daran, dass Scalar nicht genau -1, sondern z.B. -1.00000001 - also ungefähr -1 - ist. Solche Rundungsfehler treten immer auf, wenn du mit Fließkommazahlen hantierst und vielleicht zeigt dein Debugger auch nur einen gerundeten Wert an (obwohl er das eigentlich nicht sollte). Ändere daher doch einfach mal deine if-Abfrage, z.B. so:
Code:
If ((Scalar > 0.9999) and (Scalar < 1.0001)) or ((Scalar < -0.9999) and (Scalar > -1.0001))
Registriert: Fr Jan 04, 2008 21:29 Beiträge: 419 Wohnort: Lübeck
machst du das in Delphi? Wenn ja, dann kannst du aus der Unit "math" die funktion abs() nehmen. Die löscht das Vorzeichen weg, bzw. liefert den absoluten Betrag der Zahl.
Die Abfrage könnte dann so aussehen:
Code:
if (abs(scalar) = 1) then begin blupp(bla); end;
evtl. könnte man auch noch ein Epsilon einbauen, also eine Toleranz um die das Skalarprodukt abweichen darf um trotzdem positiv zu testen. Das hat den Grund, dass durch einige Berechnungen ggf. intern im Rechner keine genaue 1 erreicht werden kann. Gerade bei Vektorrechnung passiert sowas häufig. Dann würde das so aussehen:
Code:
if (abs(abs(scalar)-1) <= Epsilon) then begin blupp(bla); end;
If ((Scalar > 0.9999) and (Scalar < 1.0001)) or ((Scalar < -0.9999) and (Scalar > -1.0001))
Hmmm, mit der Abfrage funktioniert es schonmal. Nach deinem Tipp habe ich mal trunc genutzt und mein Scalar war Null, sieht also wirklich so aus als wäre mein "Scalar" irgendwo krumm :/
Sellmann hat geschrieben:
Code:
if (abs(scalar) = 1) then begin blupp(bla); end;
Diese Abfrage funktioniert so leider bei mir nicht, aber das liegt wohl halt daran, dass sich mein "Scalar" irgendwo bei -0.99999~ tummelt, und der absolute Betrag somit dann auch irgendwo bei 0.99999~ liegt.
Sellmann hat geschrieben:
Code:
if (abs(abs(scalar)-1) <= Epsilon) then begin blupp(bla); end;
Diese Abfrage hingegen funktioniert super, jedoch stellt sich mir jetzt die Frage wie man Epsilon wählen sollte, dass nicht aus Versehen ein falsches Vektorpaar erkannt wird. Das ist nämlich auch mein Problem mit dem ersten Code von mrtrain. Ich kann leider nicht beeinflussen wie groß/klein die Winkel zwischen den Vektoren werden, somit kann es durchaus passieren dass ein Winkel 0,001° groß/klein ist. :/
Oder gibt es vielleicht noch eine andere Variante dass die "falsche" -1 als echte erkannt wird.
Registriert: Do Mai 20, 2010 10:54 Beiträge: 10
Programmiersprache: C/C++
Mal ne prinzipielle Anmerkung.
Angenommen, du hast 2 Kanten, Kante 1 wird durch die Vertices A und B aufgespannt, Kante 2 durch die Vertices C und D.
Wenn du überprüfen möchtest, ob die Kante doppelt vorhanden ist, könntest du nun testen, ob Vertex A was die Position betrifft identisch mit Vertex C oder D ist. Sollte dies der Fall sein und ist Vertex B zudem identisch mit Vertex D oder C, dann liegt die Kante doppelt vor.
Identisch wären zwei Vertices dann, wenn der quadratische Abstand kleiner als eine von dir vorgegebene Mindestdistanz wäre.
Registriert: Fr Jan 04, 2008 21:29 Beiträge: 419 Wohnort: Lübeck
es geht nicht um identische vektoren, sondern um Strecken die auf der gleichen Gerade liegen. Dann ist der Ansatz mit dem Skalarprodukt schon richtig, weil ich damit erkennen kann, ob ein Punkt sich nicht auf der geraden befindet.
Edit: befindest du dich im 2D- oder 3D-Raum? Es gibt nähmlich noch die Möglichkeit den kürzesten Abstand der Punkte zur Gerade zu berechnen. Dazu musst du lediglich den zu testenden Punkt auf den normierten Vektor projezieren (einfaches skalarprodukt), der die kürzeste Distanz beschreibt. anhand der Distanz könntest du viel eher erkennen, ob der Vektor auf der Geraden liegt oder nicht, da der wert absolut ist und nicht eine Beschreibung per Winkel. Um den Distanzvektor zu erhalten, muss man in 2D die X- und Y-Komponente des Vektors der die Gerade beschreibt vertauschen und das Vorzeichen der Y-Komponente umdrehen. das ganze normieren, anschließend mit dem zu testenden Punkt und dem neuen Vektor ein Skalarprodukt berechnen und davon den absoluten Betrag betrachten. Das ist die kürzeste entfernung zwischen Gerade und Punkt. In 3D ist das etwas komplizierter. Da muss man den Stützvektor der Geraden vom zu testenden Punkt abziehen. anschließend bildet man das Kreuzprodukt aus dem Richtungsvektor der Geraden und dem Stützvektor des Punktes. man erhält eine Normale, die die Ebene beschreibt durch die deine gerade verläuft und in der sich auch der Punkt befindet. Unser Problem ist ab jetzt nur noch 2D... fast. das Kreuzprodukt von der Ebenennormale und der Geradenrichtung ist jetzt ein Vektor, der von der Geraden aus genau auf deinen Punkt ausgerichtet sein sollte (rechtwinklig zur geraden). der wird normiert, der punkt mit dem skalarprodukt raufprojeziert und schon hast du den absoluten Abstand zwischen Punkt und Gerade. Das machst du dann mit den beiden punkten, die deine Strecke bilden. ist für einen der beiden Punkte der Abstand größer als Epsilon liegt die Strecke nicht auf der Geraden. Wie groß deine Toleranz sein soll muss du dir selbst ausdenken.
Edit2: Sollte dieser Test ergeben, dass die Strecke sich auf deiner Geraden befindet und Sie soll definitiv auch dort sein, kannst du die Punkte um ihren Betrag entgegen des Distanzvektors verschieben. Beim nächsten Test sollte der Abstand dann fast exakt 0 sein, womit die Kanten sich nahezu perfekt überlagern... falls das gewollt ist.
Um den Distanzvektor zu erhalten, muss man in 2D die X- und Y-Komponente des Vektors der die Gerade beschreibt vertauschen und das Vorzeichen der Y-Komponente umdrehen. das ganze normieren, anschließend mit dem zu testenden Punkt und dem neuen Vektor ein Skalarprodukt berechnen und davon den absoluten Betrag betrachten. Das ist die kürzeste entfernung zwischen Gerade und Punkt.
Nicht ganz. Die Gerade hat auch noch einen Abstand von Nullpunkt. Der muss noch abgezogen werden, dann hat man den Abstand des Punktes zur Geraden.
Mitglieder in diesem Forum: 0 Mitglieder und 14 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.