Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Pixelkoordinaten einer Linie (https://www.delphipraxis.net/96657-pixelkoordinaten-einer-linie.html)

calculon 28. Jul 2007 17:15


Pixelkoordinaten einer Linie
 
Hi Leute,

ich will eine Prüfung durchführen, ob sich zwischen zwei Punkten ein Punkt befindet und habe mir gedacht eine Linie zwischen diesen zwei Punkten zu zeichnen:

Delphi-Quellcode:
image1.canvas.moveto(10,10);
image1.canvas.lineto(20,20);
Kann ich mir die Koordinatenliste aller einzelnen Punkte ausgeben lassen oder gibt es eine Möglichkeit eine "virtuelle" Linie zu erzeugen und deren Koordinaten sich ausgeben zu lassen?

Gruß

Calculon
--

3_of_8 28. Jul 2007 17:23

Re: Pixelkoordinaten einer Linie
 
Stichwort: Lineare Funktion

Jede Linie (naja, außer einer senkrechten) lässt sich als lineare Funktion darstellen. Eine lineare Funktion ist eine Funktion f(x)=mx+t. Wenn du also zwei Punkte P1(x1|y1) und P2(x2|y2) hast, kannst du m und t folgendermaßen berechnen:

t=y1
m=(y2-y1)/(x2-x1)

Wenn du jetzt einen Punkt P3(x3|y3) hast, musst du nur noch die Koordinaten einsetzen, wenn also folgende Gleichung gilt, liegt P3 auf der Gerade P1P2:
y3=x3*m+t

Wenn du wissen willst, ob P3 auf der Strecke [P1P2] liegt, musst du noch überprüfen, ob x1<=x2<=x3.

Eine Ausname ist, wie gesagt, eine senkrechte Gerade (also mit y1=y2), da musst du überprüfen, ob y3=y1. Bei einer senkrechten Strecke musst du außerdem noch überprüfen ob y1<=y2<=y3.

calculon 28. Jul 2007 17:25

Re: Pixelkoordinaten einer Linie
 
Vielen Dank für die Lehrstunde! Setze so das um! Muss mal anmerken: :dp:

Namenloser 28. Jul 2007 17:30

Re: Pixelkoordinaten einer Linie
 
Hi,

ich würde zuerst den Winkel zwischen dem Startpunkt und dem Endpunkt der Linie errechnen. Dann würde ich den Winkel zwischen dem Startpunkt und dem zu Prüfenden Punkt ermitteln und die beiden Winkel vergleichen: Wenn sie nicht überinstimmen, kann auch der Punkt nicht auf der Linie liegen. Wenn der Winkel jedoch überinstimmt, prüfst du, wie weit er vom Anfangs- und Endpunkt der Linie entfernt ist: die Distanz darf bei beiden maximal die Länge der Linie betragen, ansonsten ist er nicht auf der linie.

Achtung: Ich bin nur ein Siebt-(bald Acht-)klässler, kann also durchaus sein, dass es einfachere/schnellere Methoden gibt, um das zu prüfen :wink:

//Edit: da war wohl jemand schneller :/

Torpedo 28. Jul 2007 17:42

Re: Pixelkoordinaten einer Linie
 
Geht auch mit Vektoren.
Man zieht einfach eine Gerade durch die 2 Punkte und Prüft, ob der 3. Punkt auch auf der Geraden Liegt.

Gerade: [x y] = [p1.x p2.y] + lambda * [p2.x-p1.x p2.y-p2.y]
Das ist die Gerade. Je nachdem welche Zahl man für lambda einsetzt, berechnet man einen anderen Punkt auf der Geraden. Gibt es ein lambda, durch das man den 3. Punkt erhält, liegt dieser auf der Geraden. (Achtung: muss nicht zwischen den Punkten liegen. Kann man später aber mit dem x-Wert überprüfen)

Gleichungssystem:

p3.x = p1.x + lambda * (p2.x-p1.x)
p3.y = p1.y + lambda * (p2.y-p1.y)

Oder kurz:
Delphi-Quellcode:
if (p1.x-p3.x)/(p1.x-p2.x) = (p1.y-p3.y)/(p1.y-p2.y) then -> auf der Geraden
Oder vielleicht auch das, wenn das obere nicht funktionieren sollte:
Delphi-Quellcode:
if abs((p1.x-p3.x)/(p1.x-p2.x)-(p1.y-p3.y)/(p1.y-p2.y))<0.001 then -> auf der Geraden
Keine Ahnung ob das jetzt so stimmt, ist schon etwas her, dass ich das in der Schule gelernt habe, aber müsste schon funktionieren. ;)

3_of_8 28. Jul 2007 17:42

Re: Pixelkoordinaten einer Linie
 
@NamenLozer: Das geht natürlich auch, aber dafür braucht man deutlich mehr Rechenschritte und Arcus-Sinus/Cosinus usw., ich glaube fast, dass meine Methode einfacher ist. (Und schneller)

Namenloser 28. Jul 2007 17:46

Re: Pixelkoordinaten einer Linie
 
@3/8: Ja, das habe ich mir schon fast gedacht, dass es auch schneller geht, aber so komischen Kram hatten wir in der Schule leider noch nicht^^. Und wenn wir es dann kriegen, hab ich es wahrscheinlich irgendwie schon so gelernt, ist eigentlich immer so :roll:
Den ganzen sin/cos kram habe ich mir auch selber beigebracht, offiziell haben wir sogar dieses Schuljahr erst Minuszahlen kennen gelernt (Und dann wundern sich alle über Pisa :wall: )

Nikolas 28. Jul 2007 17:56

Re: Pixelkoordinaten einer Linie
 
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.

Wenn das Ganze also ein Zeichenprogramm werden soll, wird man mit den Verfahren nicht glücklich, da sie alles sehr genau nehmen.

@ torpedo: ''(Achtung: muss nicht zwischen den Punkten liegen. Kann man später aber mit dem x-Wert überprüfen) ''
Überleg nochmal, was das Lamda eigentlich bedeutet und ob man nicht vielleicht auch nur damit entscheiden kann, ob der Punkt zwischen den beiden andere liegt.

@ 3of8: besuchst du nicht diese Fernuni Hagen und hörst Mathe? In dem Fall solltest du f(x)=mx+c (c<>0) wirklich nicht als lineare Funktion bezeichnen.

@ NamensLozer: ein Sinus/Cosinus dauert etwa 200 Ticks, eine Multiplikation etwa 8, was du brauchst ist aber der asin, der dann schon mal seine 2000 Ticks braucht. Wenn es also anders geht, sollte man die Finger von den Trigonometrischen Funktionen lassen

Torpedo 28. Jul 2007 17:59

Re: Pixelkoordinaten einer Linie
 
Zitat:

Zitat von Nikolas
@ torpedo: ''(Achtung: muss nicht zwischen den Punkten liegen. Kann man später aber mit dem x-Wert überprüfen) ''
Überleg nochmal, was das Lamda eigentlich bedeutet und ob man nicht vielleicht auch nur damit entscheiden kann, ob der Punkt zwischen den beiden andere liegt.

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? :gruebel:

3_of_8 28. Jul 2007 18:02

Re: Pixelkoordinaten einer Linie
 
Erstmal studiere ich Informatik, die Mathematik, die ich da habe, ist in etwa so, dass ich mich jedes mal freue, wenn ich eine Zahl sehe.

Also für mich ist f(x)=mx+t eine ziemlich lineare Funktion. An der Schule lernt man eine lineare Funktion als f(x)=mx+t kennen. Wenn man das ganze jetzt streng mit Vektorräumen macht, ist es natürlich keine lineare Funktion mehr, da schon das erste Axiom (Homogenität) nicht mehr erfüllt ist. (a*(mx+t)<>m(a*x)+t).

Wir wollen ja nicht gleich mit Kanonen auf Spatzen schießen, indem wir das ganze hier auf Universitätsniveau heben. ;)

Nikolas 28. Jul 2007 18:18

Re: Pixelkoordinaten einer Linie
 
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)

calculon 28. Jul 2007 18:27

Re: Pixelkoordinaten einer Linie
 
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:

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
--

3_of_8 28. Jul 2007 18:31

Re: Pixelkoordinaten einer Linie
 
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. ;)

Torpedo 28. Jul 2007 18:32

Re: Pixelkoordinaten einer Linie
 
Zitat:

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.

Nikolas 28. Jul 2007 18:34

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:
x3 := mdaten.daten[nummer].X;
  y3 := mdaten.daten[nummer].Y;
Nur so: vielleicht solltest du 'Daten' eher in 'Position' umbenennen, sonst wirds unübersichtlich.

calculon 28. Jul 2007 18:47

Re: Pixelkoordinaten einer Linie
 
Zitat:

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:

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
--

Nikolas 28. Jul 2007 19:00

Re: Pixelkoordinaten einer Linie
 
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...

Hawkeye219 28. Jul 2007 20:03

Re: Pixelkoordinaten einer Linie
 
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

Torpedo 28. Jul 2007 20:12

Re: Pixelkoordinaten einer Linie
 
Habe jetzt mal das mit den Vektoren und der Differenzialrechnung durchgerechnet:

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

Nikolas 28. Jul 2007 20:34

Re: Pixelkoordinaten einer Linie
 
könntest du das mal ausführlicher hinschreiben? Mich wundert besonders die Wurzel aus einzelnen Koordinaten.

jfheins 28. Jul 2007 21:02

Re: Pixelkoordinaten einer Linie
 
Zitat:

Zitat von Nikolas
könntest du das mal ausführlicher hinschreiben? Mich wundert besonders die Wurzel aus einzelnen Koordinaten.

sqr quadriert, die Wurzelfunktion war sqrt ;)

Torpedo 28. Jul 2007 21:04

Re: Pixelkoordinaten einer Linie
 
Ich habe das ganze einfach im Taschenrechner eingegeben und ableiten lassen (dauert ganz schön lange...) dann auf 0 gesetzt und auf lambda auflösen lassen.
Dann ist die oben genannte Formel rausgekommen. Habe es auch durchgetestet. Ich kann die Punkte drehen und plazieren wie ich will, es scheint immer zu stimmen.
Den Abstand zur Geraden rechne ich aus, indem ich noch einen Vektor vom Punkt P4 auf der Geraden (den ich mit Lambda ausgerechnet habe) zum untersuchten Punkt erstelle und den Betrag berechne:
abstand := sqrt(sqr(p3.x-p4.x)+sqr(p3.y-p4.y));

Als Quellcode: (nur schnell runtergetippt, nicht getestet!)
Delphi-Quellcode:
function Abstand (const p1, p2, p3: TPoint): double;
var
  p4: TPoint;
  lambda: double;
begin
  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)));
  p4.x := p1.x+lambda*(p2.x-p1.x);
  p4.y := p1.y+lambda*(p2.y-p1.y);
  Result := sqrt(sqr(p3.x-p4.x)+sqr(p3.y-p4.y));
end;
Kann sein dass Delphi hier mit Integer rechnet (wegen TPoint), dann kommt das falsche raus. Ansonsten sollte es stimmen.

Nikolas 28. Jul 2007 21:20

Re: Pixelkoordinaten einer Linie
 
sqr...sqrt...kann doch mal passieren...

Genau so hatte ich mir das vorgestellt. Wobei die Variante mit den Geraden auch noch per Hand einfach zu berechnen ist.
Du ignorierst aber noch das Lambda aus [0,1] sein muss. Wenn Lambda nicht in diesem Intervall liegt, müsstest du irgendeinen Fehler zurückgeben, z.B. den Abstand auf -1 setzen, dass klar ist, dass der Punkt auf keiner noch so breiten Linie liegt. Aber ein bischen Arbeit soll der Fragensteller auch noch haben.
Welchen Taschenrechner hast du da drauf losgelassen? So ein kleines Rechnzentrum wie den Ti 92 Voyage?

Torpedo 28. Jul 2007 21:31

Re: Pixelkoordinaten einer Linie
 
Habe 10 Minuten den TI 89 Titanium rechnen lassen. Als er dann immer noch nicht fertig war habe ich die Testversion von Derive6 runtergeladen und es damit lösen lassen (weniger als 1 Sekunde :shock:).

calculon 29. Jul 2007 11:56

Re: Pixelkoordinaten einer Linie
 
Delphi-Quellcode:
function Abstand (const p1, p2, p3: TPoint): double;
var
  p4: TPoint;
  lambda: double;
begin
  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)));
  p4.x := p1.x+lambda*(p2.x-p1.x);
  p4.y := p1.y+lambda*(p2.y-p1.y);
  Result := sqrt(sqr(p3.x-p4.x)+sqr(p3.y-p4.y));
end;
Zitat:

Zitat von Torpedo
Kann sein dass Delphi hier mit Integer rechnet (wegen TPoint), dann kommt das falsche raus. Ansonsten sollte es stimmen.

Ja, ist so, so geht es:

Delphi-Quellcode:
function Abstand (const x1, y1, x2, y2, x3, y3: Integer): double;
var
  x4, y4: double;
  lambda: double;
begin
  lambda := (sqr(x1)-x1*(x2+x3)+x2*x3+(y1-y2)*(y1-y3))/(sqr(x1)-2*x1*x2+sqr(x2)+sqr((y1-y2)));
  x4 := x1+lambda*(x2-x1);
  y4 := y1+lambda*(y2-y1);
  Result := sqrt(sqr(x3-x4)+sqr(y3-y4));
end;
Funktioniert super! Jetzt hab' ich noch'n Verständnisproblem. Die Abweichung von 0 wird hier mathematisch angegeben. Kann ich die Werte in Pixel umrechnen? Wie kann ich Toleranzen definieren?

Bsp.:
P1(0,0), P2(200,200); P3(100,101)

Die function liefert: 0,707..

Das heißt der Punkt liegt mathematisch (numerisch) nicht exakt zwischen P1 und P2, jetzt hab' ich aber keine pixelmäßige Vorstellung der Abweichung (heißt das ca. 70% eines Pixels Abweichung?).

[edit]
Hab's jetzt so und funktioniert wunderbar. Nochmals ein drittes Dankeschön an die ganzen Antworten!
Delphi-Quellcode:
function TSpieler.FreieSicht(const x1,y1,x2,y2,dicke,spielernummer: Integer): boolean;
var
x3, y3: integer;
x4, y4, lambda: double;
begin
  x3 := mdaten.daten[spielernummer].X;
  y3 := mdaten.daten[spielernummer].Y;
  lambda := (sqr(x1)-x1*(x2+x3)+x2*x3+(y1-y2)*(y1-y3))/(sqr(x1)-2*x1*x2+sqr(x2)+sqr((y1-y2)));
  x4 := x1+lambda*(x2-x1);
  y4 := y1+lambda*(y2-y1);
  // edit: (Danke für den Hinweis @Nikolas)

  {if not (((x3 >= x1) and (x3 <= x2)) or ((x3 <= x1) and (x3 >= x2))) then
    begin
      result := false;
      exit;
    end;} // <-- nö, passt au no net

  { muss mal doch genauer überlegen, wie man die Eingrenzung durchführen muss; }

  // /edit
    if round(sqrt(sqr(x3-x4)+sqr(y3-y4))) <= dicke then
      result := true
    else
      result := false;
end;
[/edit]

Gruß

Calculon
--

Nikolas 29. Jul 2007 12:28

Re: Pixelkoordinaten einer Linie
 
Zitat:

Funktioniert super!
Das glaube ich nicht. Du solltest wenigstens versuchen, zu verstehen, was du machst, wenn du anstatt selbst zu rechnen Copy-Paste machst.

schau mal was rauskommt, wenn deine Linie durch 0/0 und 50/50 gegeben ist und teste mal den Punkt 100/100...


Zitat:

Das heißt der Punkt liegt mathematisch (numerisch) nicht exakt zwischen P1 und P2, jetzt hab' ich aber keine pixelmäßige Vorstellung der Abweichung (heißt das ca. 70% eines Pixels Abweichung?).
Ja, das heisst es. (wobei 70% eines Pixels eher ein Flächenmaß ist. genauer: der Punkt liegt etwa 70% einer Pixelbreite von der Geraden (nicht Strecke!) entfernt)

Zitat:

Wie kann ich Toleranzen definieren?
och komm. Das wurde schon mehrmals explizit erklärt. Was soll denn diese Toleranz bedeuten? (einfach mal in Worten formulieren)


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:54 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