AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi Überprüfen ob Mausklick in bestimmten bereich war

Überprüfen ob Mausklick in bestimmten bereich war

Ein Thema von xZise · begonnen am 30. Jul 2006 · letzter Beitrag vom 26. Mär 2012
Antwort Antwort
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.374 Beiträge
 
Delphi 12 Athens
 
#1

AW: Überprüfen ob Mausklick in bestimmten bereich war

  Alt 23. Mär 2012, 13:30
Ab XE2 geht auch sowoas, welches man, für D2006/TD bis XE über einen Record-Helper, selber nachrüsten kann.
Delphi-Quellcode:
var
  R: TRect;
  P: TPoint;
begin
  if R.Contains(P) then
    ...
Aber bisher sind dort nur Methoden für rechteckige Dinge integriert.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (23. Mär 2012 um 13:32 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#2

AW: Überprüfen ob Mausklick in bestimmten bereich war

  Alt 23. Mär 2012, 14:07
Es gäbe noch die möglichkeit über WindowfromPoint diese methode verwende ich bei PictureBoxen bei meinem Mediaplayer
um zu verhindern das eine function wenn meine Maus sich nicht innerhalb der x,y position befindet nach dem klick
auf einer als Button ausgelegten picBox ausgeführt wird.

Code:
GetCursorPos pos
If WindowFromPoint(pos.X, pos.Y) = PicButton(Index).hWnd Then
Habe jetzt nicht nachgeschaut wie sich das in Delphi verwirklichen läßt.

ups.. hab mich da wohl verlesen

gruss

Geändert von EWeiss (23. Mär 2012 um 14:17 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#3

AW: Überprüfen ob Mausklick in bestimmten bereich war

  Alt 23. Mär 2012, 16:03
Hier, eine etwas allgemeinere Lösung SAT (Separating Axis Theorem)

Kurze Erläuterung der Funktionsweise (soweit ich das richtig in Erinnerung habe):
Man berechnet zu allen Seiten beider Polygone schrittweise die Normalen, und projeziert alle Punkte auf diese Achse (Normale). Dann berechnet man sich die Min-Max Werte auf der Achse für Polygon 1 & 2. Schneiden sich nun diese beiden Bereiche nicht, so gibt es keine Kollision -> die Überprüfung kann vorzeitig beendet werden. Ansonsten kommt es höchstwahrscheinlich (nicht sicher!) zu einer Kollision.

Bild 1
Bild 2
(bei Bild 2 sieht man, dass der grüne und rote Bereich sich nicht schneiden -> keine Kollision)

Delphi-Quellcode:
type
  TVector = record
    X, Y: Single;
    procedure Assign(const AX, AY: Single);
  end;
  TVectorArray = Array of TVector;
  PPolygon = ^TPolygon;
  TPolygon = TVectorArray;

procedure TVector.Assign(const AX, AY: Single);
begin
  X := AX;
  Y := AY;
end;

function vector(const AX, AY: Single): TVector;
begin
  Result.Assign(AX, AY);
end;

function scalarProduct(const A, B: TVector): Single;
begin
  Result := A.X*B.X + A.Y*B.Y;
end;

procedure normalize(var V: TVector);
var
  size: Single;
begin
  size := SQRT(scalarProduct(V, V));
  if size <> 0 then V.Assign(V.X/size, V.Y/size);
end;

function normal(const V: TVector): TVector;
begin
  Result.Assign(V.Y, -V.X);
end;

function BoundingBoxCollisionCheck(const A1, A2, B1, B2: TVector): Boolean; overload;
{  1
    +---------+
    |        |
    |        |
    +---------+ 2
}

begin
  Result := not((A1.X > B2.X) or (A2.X < B1.X) or
    (A1.Y > B2.Y) or (A2.Y < B1.Y));
end;

function BoundingBoxCollisionCheck(const PolyA, PolyB: TPolygon): Boolean; overload;
var
  boxA1, boxA2,
  boxB1, boxB2: TVector;
  procedure createBoundingBox(const P: TPolygon; var bbox1, bbox2: TVector);
  var
    i: Integer;
  begin
    for i := 0 to High(P) do
    begin
      if P[i].X < bbox1.X then
        bbox1.X := P[i].X
      else
      if P[i].X > bbox2.X then
        bbox2.X := P[i].X;
      if P[i].Y < bbox1.Y then
        bbox1.Y := P[i].Y
      else
      if P[i].Y > bbox2.Y then
        bbox2.Y := P[i].Y
    end;
  end;
begin
  with PolyA[0] do
  begin
    boxA1.Assign(X, Y);
    boxA2.Assign(X, Y);
  end;
  with PolyB[0] do
  begin
    boxB1.Assign(X, Y);
    boxB2.Assign(X, Y);
  end;
  createBoundingBox(PolyA, boxA1, boxA2);
  createBoundingBox(PolyB, boxB1, boxB2);
  Result := BoundingBoxCollisionCheck(boxA1, boxA2, boxB1, boxB2);
end;

function SATCollisionCheck(const PolyA, PolyB: TPolygon): Boolean;
var
  P1, P2: PPolygon;
  function collisionCheck: boolean;
  var
    len: Integer;
    i: Integer;
    n: TVector;
    minMaxA, minMaxB: TVector;
    procedure getMinMaxAxisMappedValues(const Polygon: PPolygon; var min, max: Single);
    // axis = n
    var
      j: Integer;
      scalar: Single;
    begin
      min := scalarProduct(Polygon^[0], n);
      max := min;
      for j := 1 to high(Polygon^) do
      begin
        scalar := scalarProduct(Polygon^[j], n);
        if (scalar < min) then
          min := scalar
        else
        if scalar > max then
          max := scalar;
      end;
    end;
    function collision1DCheck(const A, B: TVector): Boolean;
    begin
      Result := not((A.X > B.Y) or (A.Y < B.X));
    end;
  begin
    Result := False;
    // gehe alle Punkte des Polygons 1 durch, bilde die Gerade und berechne darauf die Normale
    len := Length(P1^);
    for i := 0 to len do
    begin
      with P1^[(i+1) mod len] do
        n := normal(vector(X - P1^[i].X, Y - P1^[i].Y)); // n = normal(AB)
      normalize(n);
      // mappe nun alle punkte beider Polygone auf die Achse (punkt * n) und merke dir
      // min max Werte
      getMinMaxAxisMappedValues(P1, minMaxA.X, minMaxA.Y);
      getMinMaxAxisMappedValues(P2, minMaxB.X, minMaxB.Y);
      // wenn beide Bereiche sich NICHT schneiden, so kommts zu keienr Kollision und es kann beendet werden
      if not collision1DCheck(minMaxA, minMaxB) then Exit;
    end;
    Result := True;
  end;
begin
  Result := False;
  if (Length(PolyA) < 2) or (Length(PolyB) < 2) then Exit;
  if not BoundingBoxCollisionCheck(PolyA, PolyB) then Exit;
  P1 := @PolyA;
  P2 := @PolyB;
  if collisionCheck then
  begin
    P1 := @PolyB;
    P2 := @PolyA;
    Result := collisionCheck;
  end;
end;
Das ganze ist noch mit Bounding Boxes optimiert.
Hf
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG

Geändert von Aphton (23. Mär 2012 um 16:12 Uhr)
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#4

AW: Überprüfen ob Mausklick in bestimmten bereich war

  Alt 23. Mär 2012, 16:07
Das Separating Axis Theorem gilt aber afair nur für konvexe Polygone.
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#5

AW: Überprüfen ob Mausklick in bestimmten bereich war

  Alt 23. Mär 2012, 16:12
Ist ja logisch, denn alle Punkte werden ohne weiteres projeziert. Allein von der Logik her ist das ersichtlich.
Daher schrieb ich
Zitat:
Ansonsten kommt es höchstwahrscheinlich (nicht sicher!) zu einer Kollision
Aber danke
Angehängte Grafiken
Dateityp: png ProblemKonkav.png (14,5 KB, 11x aufgerufen)
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG

Geändert von Aphton (23. Mär 2012 um 16:25 Uhr)
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.100 Beiträge
 
Delphi XE2 Professional
 
#6

AW: Überprüfen ob Mausklick in bestimmten bereich war

  Alt 24. Mär 2012, 06:57
Hab das nur überflogen, aber ich glaube das Thema hatten wir hier schon mal:http://www.delphipraxis.net/598273-post18.html
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Root2k

Registriert seit: 7. Jun 2011
Ort: Ulm
49 Beiträge
 
Delphi XE Enterprise
 
#7

AW: Überprüfen ob Mausklick in bestimmten bereich war

  Alt 26. Mär 2012, 07:05
Danke für die vielen hilfreichen Beiträge.
Damit habt Ihr mir schon mal sehr weitergeholfen!
  Mit Zitat antworten Zitat
Antwort Antwort

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 16:40 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