AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Pixelkoordinaten einer Linie
Thema durchsuchen
Ansicht
Themen-Optionen

Pixelkoordinaten einer Linie

Ein Thema von calculon · begonnen am 28. Jul 2007 · letzter Beitrag vom 29. Jul 2007
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von Nikolas
Nikolas

Registriert seit: 28. Jul 2003
1.528 Beiträge
 
Delphi 2005 Personal
 
#11

Re: Pixelkoordinaten einer Linie

  Alt 28. Jul 2007, 18:18
Zitat:
Erstmal studiere ich Informatik,
oh. tschuldige. Aber affin linear klingt einfach lustiger. Alternativ auch einfach Geradengleichung.

Zitat:
Hm.. Lambda ist doch der Faktor, mit dem der Richtungsvektor multipliziert bzw. verlängert wird. Wenn der bei P1 startet und nicht negativ ist, kann der erhaltene Punkt doch immer entweder zwischen den zwei Punkten oder darauf, oder hinter dem 2. Punkt liegen, oder?
Ja, das stimmt. Welchen Wert hat den Lampda kurz vor, bei und hinter dem zweiten Punkt?

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)
Erwarte das Beste und bereite dich auf das Schlimmste vor.
  Mit Zitat antworten Zitat
Benutzerbild von calculon
calculon

Registriert seit: 16. Sep 2006
256 Beiträge
 
Delphi 7 Personal
 
#12

Re: Pixelkoordinaten einer Linie

  Alt 28. Jul 2007, 18:27
Zitat:
Die Frage ist nur, ob die Antwort zum Problem passt. Leider wurde es nicht genau beschrieben.
Interessant ist doch, ob es hier um Pixel oder Punkte geht. (Integer oder real) die vorgeschlagenen verfahren laufen auf das zweite herraus, wobei der Borg nicht erklärt hat, wann eine Gleichung wahr ist, also wann zwei Zahlen gleich sind.
Es geht um Pixel (Integer).

Zitat von Nikolas:
Wenn das Ganze also ein Zeichenprogramm werden soll, wird man mit den Verfahren nicht glücklich, da sie alles sehr genau nehmen.
Es geht um ein Spiel.

Meine Function sieht nun so aus und scheint zu funktionieren:

Delphi-Quellcode:
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;
Das mit den Vektoren werd' ich mir mal auch genauer anschauen. Auf jeden Fall Danke für die Hilfe!

Gruß

Calculon
--
  Mit Zitat antworten Zitat
Benutzerbild von 3_of_8
3_of_8

Registriert seit: 22. Mär 2005
Ort: Dingolfing
4.129 Beiträge
 
Turbo Delphi für Win32
 
#13

Re: Pixelkoordinaten einer Linie

  Alt 28. Jul 2007, 18:31
Delphi-Quellcode:
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;
Das finde ich etwas einfacher.
Manuel Eberl
„The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.“
- Terry Pratchett
  Mit Zitat antworten Zitat
Torpedo

Registriert seit: 21. Dez 2003
410 Beiträge
 
#14

Re: Pixelkoordinaten einer Linie

  Alt 28. Jul 2007, 18:32
Zitat von Nikolas:
Ja, das stimmt. Welchen Wert hat den Lampda kurz vor, bei und hinter dem zweiten Punkt?
Ah genau, daran habe ich gar nicht gedacht
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.
  Mit Zitat antworten Zitat
Benutzerbild von Nikolas
Nikolas

Registriert seit: 28. Jul 2003
1.528 Beiträge
 
Delphi 2005 Personal
 
#15

Re: Pixelkoordinaten einer Linie

  Alt 28. Jul 2007, 18:34
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:
x3 := mdaten.daten[nummer].X;
  y3 := mdaten.daten[nummer].Y;
Nur so: vielleicht solltest du 'Daten' eher in 'Position' umbenennen, sonst wirds unübersichtlich.
Erwarte das Beste und bereite dich auf das Schlimmste vor.
  Mit Zitat antworten Zitat
Benutzerbild von calculon
calculon

Registriert seit: 16. Sep 2006
256 Beiträge
 
Delphi 7 Personal
 
#16

Re: Pixelkoordinaten einer Linie

  Alt 28. Jul 2007, 18:47
Zitat von Nikolas:
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?
Ich weiß, was du meinst, das Problem wird später behandelt Am coolsten wäre es halt schon, wenn der Funktion die Dicke der Linie (Canvas.Pen-mäßig in Integer) mitgegeben werden könnte...

Zitat von Nikolas:
Nur so: vielleicht solltest du 'Daten' eher in 'Position' umbenennen, sonst wirds unübersichtlich.
Daten umfasst mehr als nur die Positionen.

Gruß

Calculon
--
  Mit Zitat antworten Zitat
Benutzerbild von Nikolas
Nikolas

Registriert seit: 28. Jul 2003
1.528 Beiträge
 
Delphi 2005 Personal
 
#17

Re: Pixelkoordinaten einer Linie

  Alt 28. Jul 2007, 19:00
Zitat:
Am coolsten wäre es halt schon, wenn der Funktion die Dicke der Linie (Canvas.Pen-mäßig in Integer) mitgegeben werden könnte...
Dann könntest du einfach meine Version umsetzen...
Erwarte das Beste und bereite dich auf das Schlimmste vor.
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#18

Re: Pixelkoordinaten einer Linie

  Alt 28. Jul 2007, 20:03
Hallo,

um noch einmal zur Ausgangsfrage nach einer "virtuellen" Linie zurückzukommen: der folgende Code verwendet die GDI-Funktion LineDDA, um alle Punkte der Linie zu ermitteln. Für jeden Punkt wird die Funktion HitTest aufgerufen, die den Abstand zwischen dem Testpunkt und dem aktuellen Punkt der Linie mit einem Schwellwert vergleicht. Wird der Schwellwert für mindestens einen Punkt unterschritten, war der Test erfolgreich.

Delphi-Quellcode:
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;
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.

Gruß Hawkeye
  Mit Zitat antworten Zitat
Torpedo

Registriert seit: 21. Dez 2003
410 Beiträge
 
#19

Re: Pixelkoordinaten einer Linie

  Alt 28. Jul 2007, 20:12
Habe jetzt mal das mit den Vektoren und der Differenzialrechnung durchgerechnet:

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))); Scheint auch zu funktionieren. Das ist dann Lambda für den Punkt auf der Geraden, der P3 am nächsten ist.
  Mit Zitat antworten Zitat
Benutzerbild von Nikolas
Nikolas

Registriert seit: 28. Jul 2003
1.528 Beiträge
 
Delphi 2005 Personal
 
#20

Re: Pixelkoordinaten einer Linie

  Alt 28. Jul 2007, 20:34
könntest du das mal ausführlicher hinschreiben? Mich wundert besonders die Wurzel aus einzelnen Koordinaten.
Erwarte das Beste und bereite dich auf das Schlimmste vor.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:16 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz