AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Punkt innerhalb Kreis?

Ein Thema von sx2008 · begonnen am 20. Dez 2008 · letzter Beitrag vom 6. Mai 2009
Antwort Antwort
Seite 1 von 3  1 23      
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#1

Punkt innerhalb Kreis?

  Alt 20. Dez 2008, 14:43
Folgende Funktion berechnet, ob ein Punkt innerhalb eines Kreise mit einem bestimmten Radius liegt.
Dabei wird der bekannte Satz des Pythagoras verwendet.
Aus Geschwindigkeitsgründen wird auf Wurzelziehen und Gleitkommaberechnungen verzichtet.
Die Unit math muss mit uses eingebunden werden.

Delphi-Quellcode:
// 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;
Falls Kreismittelpunkt und/oder der Testpunkt nur in x- und y-Werten vorliegen, kann man die Funktion Point() verwenden:
if PointInCircle(Point(shape.Left, shape.Top), Point(x,y), 50) >= 0 then ...
  Mit Zitat antworten Zitat
CalganX

Registriert seit: 21. Jul 2002
Ort: Bonn
5.403 Beiträge
 
Turbo Delphi für Win32
 
#2

Re: Punkt innerhalb Kreis?

  Alt 20. Dez 2008, 14:56
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.
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#3

Re: Punkt innerhalb Kreis?

  Alt 20. Dez 2008, 15:08
Zitat von CalganX:
Warum liefert die Funktion einen Integer und keinen Boolean zurück?
Weil es mathematisch gesehen 3 Fälle sind: im Kreis, auf der Kreislinie und Ausserhalb.
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:
if PointInCircle(M1, M2, Radius1+Radius2) = 0 then ... Wer mag, kann sich die Funktion natürlich so umschreiben, dass ein Boolean zurückgeliefert wird.
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.540 Beiträge
 
Delphi 11 Alexandria
 
#4

Re: Punkt innerhalb Kreis?

  Alt 20. Dez 2008, 15:13
Für SquareInt kann man auch die Builtin-Funktion Sqr benutzen . Außerdem steht ein paar Threads weiter unten ein weiterer zu diesem Thema.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.007 Beiträge
 
Delphi 12 Athens
 
#5

Re: Punkt innerhalb Kreis?

  Alt 20. Dez 2008, 15:33
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

result := Sign(Sqr(radius) - Sqr(a.x-b.x) - Sqr(a.y-b.y)); läuft auf meinem System ca. 10% schneller als die Integer-Variante

result := Sign(SquareInt(radius) - SquareInt(a.x-b.x) - SquareInt(a.y-b.y)); während die leicht optimierte Version

Delphi-Quellcode:
var
  x, y: Integer;
begin
  x := (a.x-b.x);
  y := (a.y-b.y);
  result := Sign(radius*radius - x*x - y*y);
end;
nur knapp 5% schneller ist als die Extended-Version.
Uwe Raabe
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#6

Re: Punkt innerhalb Kreis?

  Alt 20. Dez 2008, 16:17
Zitat von Uwe Raabe:
... SQR() ...läuft auf meinem System ca. 10% schneller als die Integer-Variante
Die Sqr()-Funktion kannte ich natürlich.
Ich hätte erwartet, dass eine Unterfunktion mit einer Integer-Multiplikation schneller ist, als Sqr() mit anschliesender impliziter Umwandlung nach Integer.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.007 Beiträge
 
Delphi 12 Athens
 
#7

Re: Punkt innerhalb Kreis?

  Alt 20. Dez 2008, 16:35
Zitat von sx2008:
Zitat von Uwe Raabe:
... SQR() ...läuft auf meinem System ca. 10% schneller als die Integer-Variante
Die Sqr()-Funktion kannte ich natürlich.
Ich hätte erwartet, dass eine Unterfunktion mit einer Integer-Multiplikation schneller ist, als Sqr() mit anschliesender impliziter Umwandlung nach Integer.
Die Integer-Multiplikation ist auch geringfügig schneller. Zeit kostet aber der zusätzliche Funktionsaufruf, während SQR ein Maschinenbefehl ist. Eine implizite Umwandlung nach Integer für das Ergebnis findet auch gar nicht statt, da für SIGN auch eine overloaded Funktion mit Extended-Parameter vorliegt.
Uwe Raabe
  Mit Zitat antworten Zitat
Namenloser

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

Re: Punkt innerhalb Kreis?

  Alt 20. Dez 2008, 17:18
Zitat von Uwe Raabe:
Zitat von sx2008:
Zitat von Uwe Raabe:
... SQR() ...läuft auf meinem System ca. 10% schneller als die Integer-Variante
Die Sqr()-Funktion kannte ich natürlich.
Ich hätte erwartet, dass eine Unterfunktion mit einer Integer-Multiplikation schneller ist, als Sqr() mit anschliesender impliziter Umwandlung nach Integer.
Die Integer-Multiplikation ist auch geringfügig schneller. Zeit kostet aber der zusätzliche Funktionsaufruf, während SQR ein Maschinenbefehl ist. Eine implizite Umwandlung nach Integer für das Ergebnis findet auch gar nicht statt, da für SIGN auch eine overloaded Funktion mit Extended-Parameter vorliegt.
Und wenn man eine inline-Funktion draus macht?
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.007 Beiträge
 
Delphi 12 Athens
 
#9

Re: Punkt innerhalb Kreis?

  Alt 20. Dez 2008, 18:25
Zitat von NamenLozer:
Und wenn man eine inline-Funktion draus macht?
Möglich, der Performance-Gewinn liegt aber allenfalls im 1-stelligen Prozentbereich. Meines Erachtens nach rechtfertigt das nicht die Einschränkungen auf Integer-Variablen. Wie schon gesagt: hat der Kreis einen ungeraden Integer-Durchmesser, wird das Ergebnis schon ungenau, weil ich sowohl den Mittelpunkt, als auch den Radius nicht mehr exakt angeben kann.
Uwe Raabe
  Mit Zitat antworten Zitat
Dipl Phys Ernst Winter

Registriert seit: 14. Apr 2009
Ort: Jena
103 Beiträge
 
Delphi 3 Professional
 
#10

Re: Punkt innerhalb Kreis?

  Alt 5. Mai 2009, 18:56
"sx2008"
Zitat:
Aus Geschwindigkeitsgründen wird auf Wurzelziehen und Gleitkommaberechnungen verzichtet.
Der Ko-Prozessor rechnet mit Gleitkommazahlen vom Typ extended allemal schneller als die CPU mit Integerwerten.

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:
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;
Noch ein Hinweis: Verwende immer den Typ extended! single und double werden vor und nach jeder Verwendung durch den Koprozessor in/aus extended Typgewandelt.
Autor: DP Ernst Winter
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


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 21:24 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz