![]() |
Re: Pixelkoordinaten einer Linie
Zitat:
Zitat:
So und da ich hier nicht nur meckern will, kommt hier mein Vorschlag: (Da du nichts über dein Alter geschrieben hast, kann es sein, dass du die Lösung noch nicht verstehst, das ganze ist auf Abiniveau) Du beginnst mit dem Vorschlag von torpedo und stellst so eine Parametergleichung auf. Jetzt kannst du jeden Punkt auf der Geraden durch einen Wert von lambda bezeichnen. Jetzt nimmst du dir den satz von Pythagoras und bestimmst den Punkt auf der Geraden, der am nächsten zum untersuchten Punkt liegt. Jeder Punkt ist als (a,b)+p*(v,w) darstellbar, dein untersuchter Punkt liege bei (x,y). Jetzt also schnell d=sqrt( (a+p*v-x)^2 + (b+p*w-y)) nach p abgelitten, Null setzen, und deinen MinimalAbstand finden. Jetzt testest du, ob der Parameter zwischen Null und Eins liegt. Warum, kann dir Torpedo erlären. Wenn du also so einen Punkt gefunden hast, schaust du nach, ob der Abstand an dieser Stelle kleiner als ein vorher von dir festgelegter Wert ist, z.B. 2Px. In diesem Fall liegt dein Punkt auf der Geraden, sonst nicht. Hier hast du den Vorteil, dass du recht exakt einstellen kannst, wie weit dein Punkt von der Geraden entfernt sein darf, und immer noch drauf liegt. Wenn du diesen Wert änderst, könntest du z.B. auch auf dickere Linien testen, was mit den anderen Verfahren nicht möglich ist, da sie ihr Augenmerk auf die mathematische Exaktheit gelegt haben. Die Rechnung oben mit dem Ableiten und Nullsetzen ist nicht allzu schön, da du noch eine quadratische Gleichung lösen musst, (glaube ich), den Code könnte ich dir aber geben, da ich sowas für meine Physikengine berechnen musste. Alternativ kannst du das gleiche Verfahren auch auf Mittelstufen Niveau fahren, ohne das es am ergebniss etwas ändert: Du stellst eine Geradengleichung wie 3of8 auf (f(x)=mx+c). Jetzt nimmst du eine weitere Gerade auf, die durch den zu betrachtenden Punkt geht, aber die Steigung -1/m hat. (g(x)=-1/m*x+d) Diese Gerade verläuft senkrecht durch die erste Gerade. (einfach mal ausprobieren). Jetzt berechnest du den Schnittpunkt der Geraden und überprüfst, ob er zwischen den beiden Punkten liegt, die die erste Gerade definieren. (einfach Kontrollieren, ob sein x (und y) wert zwischen den Werten der Punkte liegt) Falls er nicht drauf liegt, bist du hier fertig und der zu betrachtende Punkt liegt nicht zwischen den Punkten. Sonst: Dieser Punkt ist der Punkt auf der geraden, der den kleinsten Abstand zum untersuchten Punkt hat. Diesen Abstand kannst du einfach mit dem Pythagoras berechnen. Dieser Wert, den du jetzt in der Hand hällst, ist der Abstand des Punkts zu Geraden. Wenn der Punkt mathematisch exakt auf der Linie sein soll, testest du den Wert auf Gleichheit mit Null, wenn du eine breitere Linie hast, einfach darauf, ob er kleiner als die halbe Linienbreite ist. Damit hast du ein auf die Linienbreite anpassbares Verfahren auf Mittelstufen Niveau. (Nur für senkrechte und waagrechte Linien musst du eine Sonderbehandlung einbauen, aber die ist wirklich einfach) |
Re: Pixelkoordinaten einer Linie
Zitat:
Zitat:
Meine Function sieht nun so aus und scheint zu funktionieren:
Delphi-Quellcode:
Das mit den Vektoren werd' ich mir mal auch genauer anschauen. Auf jeden Fall Danke für die Hilfe!
function TSpieler.FreieSicht(x1,y1,x2,y2,nummer:integer):boolean;
var m: double; // <-- Steigungskonstante x3, y3: integer; // <-- Spielerkoordinaten begin x3 := mdaten.daten[nummer].X; y3 := mdaten.daten[nummer].Y; // Wenn P1 und P2 senkrecht stehen: if (x1 = x2) and (x3 = x1) then begin if ((y3 >= y1) and (y3 <= y2)) or ((y3 <= y1) and (y3 >= y2)) then begin result := true; // innerhalb der Strecke [P1P2] end else begin result := false; // außerhalb der Strecke [P1P2] end; exit; end; m := (y2-y1)/(x2-x1); // Berechnung der Steigung if (y3 = round(x3 * m + y1)) then begin if ((x3 >= x1) and (x3 <= x2)) or ((x3 <= x1) and (x3 >= x2)) then begin result := true; // innerhalb der Strecke [P1P2] end else begin result := false; // außerhalb der Strecke [P1P2] end; exit; end else begin result := false; exit; end; end; Gruß Calculon -- |
Re: Pixelkoordinaten einer Linie
Delphi-Quellcode:
Das finde ich etwas einfacher. ;)
function TSpieler.FreieSicht(x1,y1,x2,y2,nummer:integer):boolean;
var m: double; // <-- Steigungskonstante x3, y3: integer; // <-- Spielerkoordinaten begin x3 := mdaten.daten[nummer].X; y3 := mdaten.daten[nummer].Y; // Wenn P1 und P2 senkrecht stehen: if (x1 = x2) and (x3 = x1) then Result:=y3 >= y1) and (y3 <= y2)) or ((y3 <= y1) and (y3 >= y2) else begin m := (y2-y1)/(x2-x1); // Berechnung der Steigung Result:=((x3 >= x1) and (x3 <= x2)) or ((x3 <= x1) and (x3 >= x2)) and (y3 = round(x3 * m + y1)); end; end; |
Re: Pixelkoordinaten einer Linie
Zitat:
Je näher an Punkt 1, desto näher ist Lambda bei 0 und je näher bei Punkt 2, desto näher ist es bei 1. Grund: Der Richtungsvektor hat seinen Startpunkt in P1 und die Spitze in P2. Also wenn man ihn mit 1 multipliziert bleibt er gleich lang und zeigt weiterhin auf P2. Wenn man ihn mit 0 multipliziert schrumpft er auch auf 0 und bleibt beim Startpunkt P1. |
Re: Pixelkoordinaten einer Linie
hast du damit auch mal ein paar Testläufe gemacht? Also, wenn dein Spieler bei 0/0 steht, nach 100/100 schaut, und du den Punkt 49/50 testest?
Delphi-Quellcode:
Nur so: vielleicht solltest du 'Daten' eher in 'Position' umbenennen, sonst wirds unübersichtlich.
x3 := mdaten.daten[nummer].X;
y3 := mdaten.daten[nummer].Y; |
Re: Pixelkoordinaten einer Linie
Zitat:
Zitat:
Gruß Calculon -- |
Re: Pixelkoordinaten einer Linie
Zitat:
|
Re: Pixelkoordinaten einer Linie
Hallo,
um noch einmal zur Ausgangsfrage nach einer "virtuellen" Linie zurückzukommen: der folgende Code verwendet die GDI-Funktion ![]()
Delphi-Quellcode:
Das Laufzeitverhalten dürfte schlechter als das der bereits vorgestellten Lösungen sein. Falls eine große Anzahl von Linien überprüft werden muß, sollte man vielleicht einen bounding box test vorschalten.
type
PHitInfo = ^THitInfo; THitInfo = record px, py : Integer; accuracy : Integer; hit : Boolean; end; procedure HitTest (X, Y: Integer; lpData: LParam); stdcall; begin with PHitInfo(lpData)^ do if (Sqr(px - X) + Sqr(py - Y) <= Sqr(accuracy)) then hit := True; end; // P1, P2 beschreiben die Linie // x, y sind die Koordinaten des zu testenden Punktes // accuracy ist eine (optionale) Empfindlichkeit für den Test (0=exakt) function LineHit (const P1, P2: TPoint; x, y: Integer; accuracy: Integer = 0): Boolean; var Info : THitInfo; begin Info.px := x; Info.py := y; Info.accuracy := accuracy; Info.hit := False; LineDDA(P1.X, P1.Y, P2.X, P2.Y, @HitTest, Integer(@Info)); Result := Info.hit; end; Gruß Hawkeye |
Re: Pixelkoordinaten einer Linie
Habe jetzt mal das mit den Vektoren und der Differenzialrechnung durchgerechnet:
Delphi-Quellcode:
Scheint auch zu funktionieren. Das ist dann Lambda für den Punkt auf der Geraden, der P3 am nächsten ist.
lambda := (sqr(p1.x)-p1.x*(p2.x+p3.x)+p2.x*p3.x+(p1.y-p2.y)*(p1.y-p3.y))/(sqr(p1.x)-2*p1.x*p2.x+sqr(p2.x)+sqr((p1.y-p2.y)));
|
Re: Pixelkoordinaten einer Linie
könntest du das mal ausführlicher hinschreiben? Mich wundert besonders die Wurzel aus einzelnen Koordinaten.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:29 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