![]() |
auf linen klicken
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
seit stundne versuche ich eine lösung zu finden wie ich checken kann ob auf eine line geklick wurden ist oder nicht. z.b. start:33,26 colli:74,67 end:96,86 wie kann ich am besten prüfen ob der colli(der klick punkt) auf dieser line steht oder nicht... ich habe mir bei wikipedia was durchgelesen aber das verstehe ich leider nicht, weil es in mahte geschrieben ist(ist anscheind eine eigene sprache)... kann mir jemmand genau erklären wie ich das schreiben muss? mir geht es nicht darum den qullcode zuhaben sondern ich möchte verstehen wie sowas geht von der technik her... ich hoffe ihr wist was ich meine im anahng ist noc hein beispiel bild(was hier vergößrst solltet): |
Re: auf linen klicken
hi,
ich habe zwar den Artikel nicht gelesen, aber ich könnt mir folgendes denken: wenn du eine bestimmte Hintergrundfarbe hast, dann kasst du doch einfach die Farbe die unter dem "colli" is abfragen. Ist diese gleich der Hintergrundfarbe dann ist die Linie nicht geklickt. |
Re: auf linen klicken
so einfach geht das leider nicht. ich möchte ein grafik programm schreiben wo verschiende objekte auf ein hintergrund sein können und das geht soweit.
wie ich sowas mit rechtecken mache weiß ich..... nur halt mit linen weiß ich das leider nicht :( :( |
Re: auf linen klicken
Hallo,
"auf linien klicken" = PointInLine, eventuell kannst du ja russisch :wink: ![]() |
Re: auf linen klicken
Du hast einen Anstieg m von dem Ausgangspunkt zum Endpunkt der Linie. Wenn nun der Anstieg m vom Ausgangspunkt zu deinem Mauspunkt gleich gross ist, dann sollte der punkt auf der Linie liegen. Nun musst du nur noch testen, ob der Mauspunkt nicht vor dem Anfang oder nach dem Ende der Linie liegt. Daher: Einfach prüfen ob der Mauspunkt innerhalb des Rechtecks liegt. Das Rechteck ergibt sich aus den Koordinaten des Anfangs- und Endpunktes der Linie.
Nur mal so theoretisch gesprochen für eine Lösung. |
Re: auf linen klicken
mit einer einfachen Verhältnisgleichung sollte es auch lösbar sein. Der Ursprung der Linie ist 0, 0 das Ende der Linie liegt bei x1, y1
Dann hasst du die Mauskoordinaten x2, y2 wenn du jetzt x1 und y1 ins Verhältnis setzt zu x2 und y2 kannst du errechnen ob dies stimmt
Code:
Wenn Fragezeischen gleich dem Wert von y2 ist (also der Errechnete Wert mit der Mausposition überein stimmt) bist du auf der Linie. Je nach Linienstärke natürlich etwas tolleranz zulassen.
x1 x2
-- = -- y1 ? |
Re: auf linen klicken
wenn ich dich recht verstehe müste ich folgendes schreiben um zu testen ob ein line angeklickt wurden ist oder nicht:
Delphi-Quellcode:
problem dabei ist nur das meine ursprungs position nicht bei 0,0 ist sondern irgenwo auf dem monitor müste ich das dann noch verändern ?
if (X1 div Y1) = (x2 div y2) then
ist makiert else nichtmakiert :Muetze1 das verstehe ich nicht was du meinst..... |
Re: auf linen klicken
Zitat:
@Muetze1 & SirThornberry: Für einen exakten Klick mag das reichen, aber der Fall ist wohl _äußerst_ unwahrscheinlich ;) . Mit der Toleranz wird das nicht funktionieren, der Mausbereich ist dann auf der einen Seite dünn wie ein Faden und auf der anderen aufgefächert. @mimi: Tut mir leid, aber es _geht_ einfach nicht einfacher als mit Vektoren. Startpunkt A, Endpunkt B, Maus C Du musst das Lot von C auf AB konstruieren. Mit dem Skalarprodukt kannst du überprüfen, ob der Lotfußpunkt überhaupt auf AB liegt: 0 <= ((B - A) . (C - A)) / |A| <= |B|. Nun musst du noch die Lotlänge errechnen, zB per Pythagoras, und überprüfen, ob sie kleiner als die Toleranz ist. Zusätzlich kannst du noch prüfen, ob |C - A| oder |C - B| < Toleranzwert ist, ob C also in einem Kreis um einen der Linienpunkte liegt. Alles aus dem Kopf, habe ich so oder so ähnlich ;) in meinem Bézier-Program benutzt. |
Re: auf linen klicken
vielen dank für eure hilfe. aber leider verstehe ich nicht viel von geometry. nur das einfachsts.
Ich weiß z.b. wie ich eine line zeichnen kann(also selbst ohne lineTo und MoveTo) und wie ich eine collision auf ein rechteck prüfen kann... mehr leider nicht... kenntst du oder einer von euch eine seite wo "computer geometry" beschrieben wird ? (in einfachen worten gefasst) und halt auf deutsch.... das währe praktisch weil ich möchte ja verstehen wie das funktioniert und nicht einfach code nehmen den es schon gibt ! |
Re: auf linen klicken
Einfacher als mit Gummibärchens lösungs gehts aber leider nicht ;)
|
Re: auf linen klicken
hier habe ich letzten ein code geschrieben(abgeschrieben aus einem buch und leicht angepasst):
Delphi-Quellcode:
da bei jedem durchlauf die position um die angeben xdiff und ydiff werte erhört nur ich weiß leider nicht wie ich das um setzten könnte... weil eine schleife wollte ich eigetnlich nicht starten !
for i:=0 to High(obj) do begin
with obj[i] do begin xWeg:=zx-px; yWeg:=zy-py; strecke:=Sqrt(Sqr(xweg)+Sqr(yweg)); schritte:=Strecke /1; xdiff:=Xweg / Schritte; ydiff:=yweg / Schritte; if zx < px then begin px:=Round(px+xDiff); end else isx:=True; if zy < py then begin py:=round(py + yDiff); end else isY:=True; if (isx = true) and (isy= true) then begin Spray(DXDraw1.Surface.Canvas,round(px),round(py),20,clred); DXDraw1.Surface.Canvas.Release; end; DXImagelist1.Items[0].Draw(dxdraw1.Surface,round(px),round(py),0); end; end; und gewisse tolleranzen würde ich auch gut finden ! |
Re: auf linen klicken
Hallo,
Die Idee, den Anstieg der Geraden mit dem Anstieg zum clickpoint zu vergleichen hat einen schwer wiegenden Nachteil, wenn ein Toleranzbereich definiert werden soll. Da würde sich die Clicktoleranz entlang der Geraden ändern. Einen Tolranzbereich (Pickbox) braucht es aber für die Bedienbarkeit des progs. Eine Schleife braucht es nicht, um fest zu stellen, dass der clickpoint auf der Linie liegt, das wird zu aufwändig. Besser ist es, einfach den Abstand des clickpoints zur line zu berechnen und wenn der klein genug ist, die line als angeclickt zu betrachten. Das geht auch ohne Vektorrechnung. grüsse der flossinger |
Re: auf linen klicken
@flossinger
könntes du bitte ein beispiel machen weil so ganz verstehe ich das noch nicht... ich werde heute mal im internet nach einer seite suchen wo Geometry mit dem computer verbunden ist! |
Re: auf linen klicken
Ja bitte gerne:
Ich habe eine line von x1,y1 nach x2,y2. Dann clicke ich und habe den clickpunkt x3,y3. Den ergänze ich mit einem weitern Punkt, so dass ich eine zweite line habe, die senkrecht auf die erste steht.
Delphi-Quellcode:
teste das mal, und du wirst sehen, dass die lines senkrecht zueinander stehen.
image1.canvas.moveto(x3,y3);
x4:=x3+(y2-y1); y4:=y3-(x2-x1); // image1.canvas.lineto(x4,y4); // test Als nächstes berechnest du den Schnittpunkt der beiden Geraden, und du kannst den Abstand daraus ableiten. grüsse, der flossinger |
Re: auf linen klicken
Liste der Anhänge anzeigen (Anzahl: 1)
Habe noch einen screenshot dazu gemacht:
so kann das aussehen. grüsse, der flossinger |
Re: auf linen klicken
Hey wo ist dann der Schnittpunkt genau?
Tomka |
Re: auf linen klicken
hier mal eine Lösung:
Delphi-Quellcode:
fLinie ist vom Typ "TRect" wobei TopLeft die den Startpunkt angibt und BottomRight den EndPunkt.
fLinie := Rect(50, 50, 200, 80);
[...] procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var lPoint : TPoint; lNeededY: Integer; begin X := X - fLinie.Left; Y := Y - fLinie.Top; lPoint := Point(fLinie.Right - fLinie.Left, fLinie.Bottom - fLinie.Top); if (X >= 0) and (Y >= 0) and (X < lPoint.X) and (Y < lPoint.Y) then begin lNeededY := Round(X * lPoint.Y / lPoint.X); if (lNeededY > Y - 5) and (lNeededY < Y + 5) then caption := 'Linie getroffen' else caption := 'Linie verfehlt'; end else caption := 'außerhalb der Linie'; end; |
Re: auf linen klicken
Der Ansatz ist leider noch ungenauer als der letzte ;) . Je senkrechter die Linie desto kleiner der Klickbereich (bei 90/270° dann ganz wech). Wobei du das X >= 0 weglassen können solltest.
|
Re: auf linen klicken
wenn "X >= 0" weggelassen wird ist es möglich auch links neben der Linie zu klicken wo sie gar nicht ist.
|
Re: auf linen klicken
Achje, habs verdreht. Stattdessen müsste du "Y >= 0" "Y > 0" heißen.
|
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" |
Re: auf linen klicken
Wahrscheinlich hast du die codeschnipsel nicht in eine Schleife integriert, die alle in Frage kommenden lines abfragt. Das wird wohl nicht so schwierig sein. Es könnten aber auch andere Gründe vorliegen. Ich habe keine Ahnung, was du gemacht hast.
Deine Umsetzung scheint noch einen grundlegenden logischen Fehler zu haben, aber wenn du den Vorschlag nicht weiter verfolgst, ist das ohnehin egal. grüsse, der flossinger |
Re: auf linen klicken
naja ich kann ja versuchen beide versionen zu benutzen bzw. zum laufen zu bringen..
ich wüßste schon gerne was an der ersten version falsch ist ! |
Re: auf linen klicken
ok,
darauf werde ich gerne später noch zurückkommen, aber mach doch bitte vorerst den nächsten Schritt: poste mal einen screenshot, wo du dir die ursprüngliche line von x1/y1 nach x2/y2 und auch die DARAUF senkrechte line von x3/y3 nach x4/y4 anzeigen lässt. Es geht also um zwei lines die im rechten Winkel zu einander stehen. der flossinger |
Re: auf linen klicken
das mach ich gerne... aber ich muss im moment was andres machen... was nicht mit programmieren zu tuen hat(leider.....)
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:08 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