Funktioniert das Ganze vielleicht auch irgendwie mit einem Polygon, bzw. einer beliebigen Form die durch ein Punkte-Array definiert ist?
Kann ich z.B. ermitteln wenn sich die Maus in einem Kreis befindet? Derzeit lege ich ein Rechteck außen herum, aber das ist je nach Form sehr ungenau.
Kreis ist einfach, da musst du nur prüfen, ob die Distanz zum Mittelpunkt kleiner dem Radius ist:
PtInCirle := sqr(X-P.X)+sqr(Y-P.Y) < sqr(R)
, wobei X und Y die Koordinaten z.B. des Cursors sind, P.X und P.Y der Mittelpunkt des Kreises und R der Radius. Die Gleichung wurde hier quadriert um die Wurzel zu sparen.
Für Polygone gibt es auch
Verfahren (engl.), aber wenn es wirklich nur um einen Kreis geht, macht es absolut keinen Sinn, das zu implementieren. Ansonsten gibt es natürlich noch die von DeddyH verwendete
API-Funktion, aber manchmal will man nicht mit Windows-Regions arbeiten...
[edit]
Hab mal meinen Port für den verlinten Algorithmus ausgegraben:
Delphi-Quellcode:
function TMapRegion.PointInRegion(APoint: TPoint): boolean;
var
Pt1, Pt2: TPoint;
PtOld, PtNew: TPoint;
i: integer;
begin
if (APoint.X >= FVertexList.BoundingBox.Left) and
(APoint.X <= FVertexList.BoundingBox.Right) and
(APoint.Y >= FVertexList.BoundingBox.Top) and
(APoint.Y <= FVertexList.BoundingBox.Bottom) and
(FVertexList.Count >= 3) then
begin
///
/// Ported from http://www.visibone.com/inpoly/
///
Result := False;
PtOld := FVertexList.Last;
for i := 0 to FVertexList.Count - 1 do
begin
PtNew := FVertexList[i];
if PtNew.X > PtOld.X then
begin
Pt1 := PtOld;
Pt2 := PtNew;
end
else
begin
Pt1 := PtNew;
Pt2 := PtOld;
end;
if ((PtNew.X < APoint.X) = (APoint.X <= PtOld.X)) and
((APoint.Y-Pt1.Y)*(Pt2.X-Pt1.X) < (Pt2.Y-Pt1.Y)*(APoint.X-Pt1.X)) then
begin
Result := not Result;
end;
PtOld := PtNew;
end;
end
else
Result := False;
end;
Bin jetzt zu Faul, den Code für normale Arrays zu verallgemeinern, aber es sollte nicht schwierig sein, ihn entsprechend abzuändern. Relevant ist übrigens nur der Teil innerhalb des if-Konstrukts. In der Abfrage davor wird nur erst mal gegen eine Bounding Box verglichen, was aber lediglich aus Performancegründen geschieht und somit weglassen werden kann.
[/edit]