![]() |
Re: auf linen klicken
Eine recht einfache Möglichkeit das Problem zu lösen ist über die Hessesche Normalform:
Delphi-Quellcode:
Edit: Falls du wirklich schauen möchtest, ob der Punkt auf der Geraden liegt (was hier unsinnig ist durch die Ungenauigkeit von Pixeln), so musst du folgendes überprüfen:
var
// Gegeben A: TPoint; // Punkt der Geraden B: TPoint; // Punkt der Geraden P: TPoint; // Punkt des Mausklicks // errechnete Werte g: TPoint; // Richtungsvektor n: TPoint; // Normalvektor d: Integer; // d = a*x + b*y HNF: Double; begin g := Point(B.X - A.X, B.Y - A.Y); n := Point(g.Y, -g.X); d := n.X * A.X + n.Y * A.Y; HNF := Abs((n.X * P.X + n.Y * P.Y - d) / Sqrt(n.X * n.X + n.Y * n.Y)); // hier Wert anpassen if HNF < 20 then ShowMessage('getroffen') else ShowMessage('daneben'); end;
Delphi-Quellcode:
if n.X * P.X + n.Y * P.Y = d then
ShowMessage('Punkt liegt auf der Geraden') else ShowMessage('Punkt liegt nicht auf der Geraden'); |
Re: auf linen klicken
Hallo,
zu der Frage, wo der Schnittpunkt ist, habe ich eine Lösung ausgearbeitet, die bewusst ohne Vektorrechnung auskommt und mit skalarer Algebra nachvollziehbar ist. Dabei habe ich eine line von x1,y1 nach x2,y2. Die senkrecte Linie darauf verläuft vom Clickpunkt x3,y3 nach x4,y4. Wobei wie gesagt x4:=x3+(y2-y1); und y4:=y3-(x2-x1); Der Schnittpunkt x,y berechnet sich nun so:
Delphi-Quellcode:
Die Distanz vom Clickpunkt zur Geraden, die durch die line verläuft beträgt:
dxa:=x2-x1;
dya:=y2-y1; dxb:=x4-x3; dyb:=y4-y3; x:=round(((y3-y1)*dxa*dxb+x1*dya*dxb-x3*dyb*dxa)/(dya*dxb-dyb*dxa)); if abs(dxa)>abs(dxb) then y:=round(((x-x1)*dya+y1*dxa)/dxa) else y:=round(((x-x3)*dyb+y3*dxb)/dxb); // die genauere Variante wird gewählt und /0 vermieden
Delphi-Quellcode:
Mit der folgenden Bedingung kann noch abgefragt werden, ob die senkrechte Gerade die line trifft, oder ob der Schnittpunkt ausserhalb der Endpunkte liegt:
dist:=round(sqrt(sqr(x3-x)+sqr(y3-y)));
Delphi-Quellcode:
Wenns Fragen gibt, nur her damit. Der code ist übrigens gut ausgetestet.
if not((((x<=x1)and(x>=x2))or((x>=x1)and(x<=x2)))
and (((y<=y1)and(y>=y2))or((y>=y1)and(y<=y2)))) then dist:=-1; grüsse, der flossinger |
Re: auf linen klicken
gut dann wollen wir mal fragen.
Tut mir leid das ich erst jetzt antworte: habe die frage aus den augen verloren :? also ich habe eine frage hierzu: dxa:=x2-x1; // MoveTo dya:=y2-y1;// MoveTo dxb:=x4-x3; // line to dyb:=y4-y3; // line to ? damit meine ich die position der line... sind die kometare richtig angeben ? und x:=round(((y3-y1)*dxa*dxb+x1*dya*dxb-x3*dyb*dxa)/(dya*dxb-dyb*dxa)); könntes du mir das bitte noch etwas genauer beschreiben\erkläeren ? Zitat:
ich möchte doch linen zeichnen die irgenwie sind: waagerecht, senkrecht, schräg, und soweiter ! vielen dank ! |
Re: auf linen klicken
Hallo Michael,
das ist doch kein Problem, wenn man eine Frage etwas aus den Augen verliert. Das geht mir auch oft so. Man hat ja so vieles im Kopf. Die Variablen dxa, dya. dxb, dyb enthalten nur Zwichenergebnisse für die Berechnung von x und y. Durch das Abspeichern dieser Zwischenergebnisse werden die Zeilen, wo x und y berechnet werden etwas vereinfacht und fallen dadurch kürzer aus. Die "senkrechte Gerade" von der ich schreibe, verläuft nicht senkrecht auf dem Bilschirm von oben nach unten. Da hast du recht, so eine Einschränkung wäre nicht gut. Ich meine die Gerade, in der ich im Posting #14 schreibe. Zitat:
Ich schlage vor, du testest einmal das, was hier aus dem Posting #14 wiederholt wurde. Wenn etwas nicht klappen sollte, kannst du gerne zurückfragen. Wenn es geklappt hat, hast du schon etwas mehr Durchblick für die Fortsetzung. Teste so, dass du in deinem Programm eine line siehst, die im rechten Winkel auf die ursprüngliche line verläuft. Poste, was dein ergebnis ist, und dann setze ich gerne fort. oT: Gratulation zum Neustart des Forums! Das war ja schon eine schöne Bescherung. grüsse, der flossinger |
Re: auf linen klicken
ich habe versucht draus eine funktion zu entwicklen.
Delphi-Quellcode:
allerdings weiß ich nicht genau was x3 und y3 bedeuteten
function GetLineClick(x1,y1,x2,y2:Integer):Boolean;
var dxa,dya,dxb,dyb,x,y,x4,y4:Integer; begin dxa:=x2-x1; dya:=y2-y1; x4:=x3+(y2-y1); y4:=y3-(x2-x1); dxb:=x4-x3; dyb:=y4-y3; x:=round(((y3-y1)*dxa*dxb+x1*dya*dxb-x3*dyb*dxa)/(dya*dxb-dyb*dxa)); if abs(dxa)>abs(dxb) then y:=round(((x-x1)*dya+y1*dxa)/dxa) else y:=round(((x-x3)*dyb+y3*dxb)/dxb); // die genauere Variante wird gewählt und /0 vermieden dist:=round(sqrt(sqr(x3-x)+sqr(y3-y))); if not((((x<=x1)and(x>=x2))or((x>=x1)and(x<=x2))) and (((y<=y1)and(y>=y2))or((y>=y1)and(y<=y2)))) then result:=false else result:=true; end; edit: x3 und y3 ist bestimmt der klickpunk mit der maus,oder ? |
Re: auf linen klicken
ja,
ganz genau: x3/y3 ist der der clickpunkt. Ds heisst, in x3 und y3 müssen die Mauskoordinaten abgespeichert werden. Dann kannst du dir auch die line von x3/y3 nach x4/y4 anzeigen lassen. der flossinger edit:tippfehler |
Re: auf linen klicken
ich habe jetzt nochmal" idontwantaname" lösung probiert !
Sie läuft besser als "flossinger" lösung allerdins habe ich dennoch ein problem: ich habe eine obj was auf ein andres liegt z.b. eine line liegt auf ein viereck dann wird die line nicht mehr erkannt:
Delphi-Quellcode:
nun die fehler:
function GetLineClickA(x1,y1,x2,y2,x3,y3:Integer):Boolean;
var // Gegeben A: TPoint; // Punkt der Geraden B: TPoint; // Punkt der Geraden P: TPoint; // Punkt des Mausklicks // errechnete Werte g: TPoint; // Richtungsvektor n: TPoint; // Normalvektor d: Integer; // d = a*x + b*y HNF: Double; begin a.x:=x1; a.y:=y1; b.x:=x2; b.y:=y2; p.x:=x3; p.y:=y3; g := Point(B.X - A.X, B.Y - A.Y); n := Point(g.Y, -g.X); d := n.X * A.X + n.Y * A.Y; HNF := Abs((n.X * P.X + n.Y * P.Y - d) / Sqrt(n.X * n.X + n.Y * n.Y)); // hier Wert anpassen if HNF < 20 then result:=True // ShowMessage('getroffen') else result:=false; // ShowMessage('daneben'); end; // verwenden tue ich das hier: function TmyList.GetItemIndex(x,y:Integer;Obj:TObjectList;state:TShiftState):Integer; var i,pIndex:Integer; r:TRect; Region: THandle; begin pIndex:=-1; for i:=0 to obj.count-1 do begin with TPaint2BasesObj(liste.items[i]) do begin if obj.Items[i] is TLine = false then begin r.left:=position.x; r.top:=position.y; r.Right:=size.x;r.Bottom:=size.y; if PtInRect(r,point(x,y)) = true then pindex:=i; end else begin if (GetLineClickA(position.x,position.y,size.x,size.y,x,y) = true) and (pindex = -1) then pindex:=i; end; end; end; if pindex > -1 then begin selobject:=TPaint2BasesObj(liste.items[pindex]); itemindex:=pIndex; end; writeLn(IntTostr(Pindex)); result:=Pindex; if pindex > -1 then begin if ssshift in state then TPaint2BasesObj(liste.items[pindex]).Sel:=True; end else begin SetSelObj(false); selobject:=bg; end; Region:=0; // Region end; bei flossinger function die ich oben gepostet habe habe ich leider folgenden fehler: ich habe wieder mehre objekte und nun platzier ich linen auf die paintbox.... nun kann ich nur noch die line und das erste objekt auswählen. :cry: |
Re: auf linen klicken
jetzt geht ihr müst einfach in der zeile
if (GetLineClickA(position.x,position.y,size.x,size.y ,x,y) = true) then das pindex - 1 rauß nehmen. das hatte ich zum testen drin... aufjedenfall geht es jetzt.. . mit" idontwantaname's" lösung ! vielen dank für eure hilfe ! |
Re: auf linen klicken
Liste der Anhänge anzeigen (Anzahl: 1)
Na dann hast du flossingers Lösung nicht richtig umgesetzt.
Wie der screenshot zeigt, funktioniert das perfekt. Anstatt zu behaupten, dass etwas nicht funktioniert, könntest du auch weitere Fragen stellen. der flossinger |
Re: auf linen klicken
also folgende:
sobalt ich mehre objekte paltze und dein code ausprobiere habe ich das problem das ich nur noch ein object und die line auswählen kann aller andren objekte sind dann "tod" |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:56 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