![]() |
Punkt innerhalb Kreis?
Folgende Funktion berechnet, ob ein Punkt innerhalb eines Kreise mit einem bestimmten Radius liegt.
Dabei wird der bekannte ![]() Aus Geschwindigkeitsgründen wird auf Wurzelziehen und Gleitkommaberechnungen verzichtet. Die Unit math muss mit uses eingebunden werden.
Delphi-Quellcode:
Falls Kreismittelpunkt und/oder der Testpunkt nur in x- und y-Werten vorliegen, kann man die Funktion Point() verwenden:
// a: Kreismittelpunkt
// b: Testpunkt // Result => // 1 = Punkt innerhalb Kreis // 0 = Punkt liegt auf Kreislinie // -1 = Punkt ausserhalb Kreis function PointInCircle(a,b:TPoint; radius:integer):integer; function SquareInt(x:integer):integer; // Hilfsfunktion: Quadrieren begin result := x * x; end; begin result := Sign(SquareInt(radius) - SquareInt(a.x-b.x) - SquareInt(a.y-b.y)); end;
Delphi-Quellcode:
if PointInCircle(Point(shape.Left, shape.Top), Point(x,y), 50) >= 0 then ...
|
Re: Punkt innerhalb Kreis?
Warum liefert die Funktion einen Integer und keinen Boolean zurück? Wenn du ohnehin auf ">= 0" prüfen musst, kannst du das auch direkt in der Funktion tun. :gruebel:
|
Re: Punkt innerhalb Kreis?
Zitat:
So kann der Anwender selbst entscheiden, ob er die Punkte, direkt auf der Kreislinie liegen noch mitrechnet oder nicht. Wenn man z.B. wissen möchte, ob sich zwei Kreise mit den Mittelpunkten M1 und M2 gerade berühren, dann kann man das so ermitteln:
Delphi-Quellcode:
Wer mag, kann sich die Funktion natürlich so umschreiben, dass ein Boolean zurückgeliefert wird.
if PointInCircle(M1, M2, Radius1+Radius2) = 0 then ...
|
Re: Punkt innerhalb Kreis?
Für SquareInt kann man auch die Builtin-Funktion Sqr benutzen ;). Außerdem steht
![]() |
Re: Punkt innerhalb Kreis?
Die Beschränkung auf Integer erscheint mir nicht sehr weise, da z.B. bei einem Kreis mit "ungeradem" Durchmesser der Mittelpunkt und der Radius eben nicht als Integer ausgedrückt werden können. Auch ist der Geschwindigkeitsnachteil von Gleitkommaoperationen bei zeitgemäßen Prozessoren durchaus zu vernachlässigen. Interessanterweise ist gerade in diesem Fall die Verwendung von Extended statt Integer etwas schneller:
Der Code
Delphi-Quellcode:
läuft auf meinem System ca. 10% schneller als die Integer-Variante
result := Sign(Sqr(radius) - Sqr(a.x-b.x) - Sqr(a.y-b.y));
Delphi-Quellcode:
während die leicht optimierte Version
result := Sign(SquareInt(radius) - SquareInt(a.x-b.x) - SquareInt(a.y-b.y));
Delphi-Quellcode:
nur knapp 5% schneller ist als die Extended-Version.
var
x, y: Integer; begin x := (a.x-b.x); y := (a.y-b.y); result := Sign(radius*radius - x*x - y*y); end; |
Re: Punkt innerhalb Kreis?
Zitat:
Ich hätte erwartet, dass eine Unterfunktion mit einer Integer-Multiplikation schneller ist, als Sqr() mit anschliesender impliziter Umwandlung nach Integer. :gruebel: |
Re: Punkt innerhalb Kreis?
Zitat:
|
Re: Punkt innerhalb Kreis?
Zitat:
|
Re: Punkt innerhalb Kreis?
Zitat:
|
Re: Punkt innerhalb Kreis?
"sx2008"
Zitat:
Was soll radius: integer? Die Komponenten von TPoint sind offensichtlich, wegen SquareInt(a.x-b.x), auch nur Integerwerte,? Diese Einschränkungen gehen viel zu weit!
Delphi-Quellcode:
Noch ein Hinweis: Verwende immer den Typ extended! single und double werden vor und nach jeder Verwendung durch den Koprozessor in/aus extended Typgewandelt.
typ
TPoint= record x, y: extended end; cons eps= 1e-14; function PointInCircle(m, p:TPoint; radius: extended):integer; var a: extended; // Abstend m - p begin a:= (m.x - p.x)*(m.x - p.x) + (m.y - p.y)*(m.y - p.y); if Abs(a)>eps then a:= sqrt(a) else a:= 0; // a könnte durch Rundungsfehler<0 sein if (a - radius)<-eps then Result:= 1 // Punkt innerhalb Kreis else if (a - radius)>eps then Result:= -1 // Punkt ausserhalb Kreis else Result:= 0 // Punkt liegt auf Kreislinie end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:30 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