AGB  ·  Datenschutz  ·  Impressum  







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

Schnittpunkt Linie vs. Kreis

Ein Thema von Namenloser · begonnen am 25. Mär 2009 · letzter Beitrag vom 15. Okt 2012
Antwort Antwort
Seite 1 von 2  1 2      
Namenloser

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

Schnittpunkt Linie vs. Kreis

  Alt 25. Mär 2009, 22:12
Ich war vorhin auf der Suche nach einem Code, mit dem sich die Schnittpunkte eines Kreises und einer Linie ausrechnen lassen. Da ich für Delphi nichst gefunden habe, habe ich folgende Funktion geschrieben:
Delphi-Quellcode:
function LineHitsCircle(LineX1,LineY1,LineX2,LineY2,
  CircleX,CircleY,CircleRadius: double; out OutPos: Double): boolean;
var
  x1, x2, x: double;
  d: double;
  d_helper: double;
  m,n: double;

  tmp: double;
begin
  LineX1 := LineX1 - CircleX;
  LineY1 := LineY1 - CircleY;
  LineX2 := LineX2 - CircleX;
  LineY2 := LineY2 - CircleY;

  if (LineX2-LineX1=0) then
  begin
    if (LineY2-LineY1=0) then
    begin
      OutPos := 0.0;
      result := sqr(LineX1)+sqr(LineY1) <= sqr(CircleRadius);
      exit;
    end
    else
    begin
      tmp := LineY1;
      LineY1 := LineX1;
      LineX1 := tmp;
      
      tmp := LineY2;
      LineY2 := LineX2;
      LineX2 := tmp;
    end;
  end;

  m := (LineY2-LineY1)/(LineX2-LineX1);
  n := LineY1-m*LineX1;
  d_helper := 4*sqr(m)*sqr(n) - 4*(1+sqr(m))*(sqr(n)+2*n-sqr(CircleRadius));

  if d_helper < 0 then
  begin
    OutPos := -1;
    result := False;
  end
  else
  begin
    d := sqrt(d_helper);
    x1 := (-2*m*n - d)/(2+2*sqr(m));
    x2 := (-2*m*n + d)/(2+2*sqr(m));

    if (x1>=LineX1) and ((x1 - LineX1)<=(x2-LineX1)) then
      x := x1
    else
      x := x2;

    OutPos := abs((x-LineX1)/(LineX2-LineX1));

    result := (OutPos >= 0.0) and (OutPos <= 1.0);
  end;
end;
Sicher noch optimierbar, und gut möglich, dass es mit Vektoren irgendwie eleganter geht (das war bisher immer so ). Die Funktion gibt keinen Punkt zurück, sondern die Stelle auf der Strecke (Gleitkommazahl von 0 (Startpunkt) bis 1 (Endpunkt)), weil das für meine Zwecke praktischer ist. Man könnte aber auch sehr einfach den Punkt ausrechnen (über die lineare Funktion, m und n sind ja gegeben). Wenn es zwei Schnittpunkte gibt, wählt die Funktion den, der am nächsten beim Startpunkt liegt.
Wenn man die If-Abfragen am Ende weglässt, hat man eine Funktion, die die Schnittpunkte einer geraden und eines Kreises berechnet.

Ich hoffe, dass eine solche Funktion nicht schon gibt in der CodeLibrary existiert. Über die Suche habe ich wie gesagt nichts gefunden.

[edit]Bugfix bei senkrechter Linie[/edit]
  Mit Zitat antworten Zitat
mr_emre_d
(Gast)

n/a Beiträge
 
#2

Re: Schnittpunkt Linie vs. Kreis

  Alt 25. Mär 2009, 22:43
Ein bisschen Theorie:

Bekannte Werte:
Mittelpunkt ( -> Mx, My )
Radius ( -> r )
Linie ( f )

-----------------

k: (x-Mx)²+(y-My)² = r²

f(x) = y = kx + d

-----------------

Gleichsetzen und ausrechnen

EDIT: Ich rechne mal mit Notepad ein Beispiel aus...

MfG
  Mit Zitat antworten Zitat
Namenloser

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

Re: Schnittpunkt Linie vs. Kreis

  Alt 25. Mär 2009, 22:59
Zitat von mr_emre_d:
Ein bisschen Theorie:

Bekannte Werte:
Mittelpunkt ( -> Mx, My )
Radius ( -> r )
Linie ( f )

-----------------

k: (x-Mx)²+(y-My)² = r²

f(x) = y = kx + d

-----------------

Gleichsetzen und ausrechnen

EDIT: Ich rechne mal mit Notepad ein Beispiel aus...

MfG
Ich verstehe nicht ganz, was du mir sagen willst Oder sitze ich schon wieder zu lange vor der Kiste?
  Mit Zitat antworten Zitat
mr_emre_d
(Gast)

n/a Beiträge
 
#4

Re: Schnittpunkt Linie vs. Kreis

  Alt 25. Mär 2009, 23:21
xD

Du willst ja die Schnittpunkte ausrechnen oder ? Ich zeig dir nur, wie es mathematisch möglich ist.
Wie weit du das in delphi implementierst ist dir überlassen

MfG

Weiter gehts:

Code:
k: (x-Mx)²+(y-My)² = r²

f(x) = y = kx + d

Konkretes Beispiel:

Mittelpunkt = ( 5 | 6 )
Radius = 5
f(x) = 2x + 3
--:

(x-5)²+(y-6)² = 25
x²-10x+25 + y²-12y+36 = 25
x²-10x + y²-12y = -36
--------------------------

x²-10x + y²-12y = -36
   (2x+3)² -> 4x²+12x+9
      -12*(2x+3) -> -24x-36

x²-10x + 4x²+12x+9 -24x-36 = -36

x²-10x -12x + 4x² + 9 =
 0


5x² - 22x + 9 = 0   |   / 5

x² - 4,4x + 1,8 = 0

( Quadratisch Gleichung auflösen: -p/2 +- SQRT( (-p/2)² - q )   |   p = -4.4   q = 1.8 )
   
   x1,2 = 2,2 +- SQRT( 4,84 - 1.8 )
   x1 = 2.2 + 1,74 -> 3.94
   x2 = 2.2 - 1,74 -> 0.46

Punkt1( 3.94 | y )
Punkt1( 0.46 | y )

y = 2x + 3 ->
Punkt1 y = 2*3.94 + 3 = 10.88
Punkt2 y = 2*0.46 + 3 = 3.92

Schnittpunkte
   Punkt1( 3.94 | 10.88 )
   Punkt2( 0.46 | 3.92 )

Graph (Kreis + F) im Anhang :)
EDIT:
Wohoo .. ich dacht mir du brauchst Hilfe - bin auf den Thread hier durch die Startseite gestoßen und habe nur deinen ersten Satz gelesen -> wusste damit nicht, dass es ein Vorschlag für die Code-Lib ist :S )

EDIT2:
Delphi-Quellcode:
type
  TPointF = record
    X, Y: Single;
  end;

  T2Points = Array[0..1] of TPointF;

...

function Intersection_Circle_Line( cRadius, cMX, cMY: Single; lKX: Single;
  const lD: Single = 0.0 ): T2Points;
{
  CIRCLE:
    cRadius  = Radius of the circle
    cMX / cMY = Center Coordinates
  LINE:
    lKX      = INCREASE
    lD        = Intersection with y-axis
}

var
  xX, X,
  C, T: Single;
begin
  xX := 1 + lKX * lKX;
  X := -cMX*2 + lKX*lD*2 + (-cMY*2)*lKX;
  C := cMX*cMX + lD*lD + (-cMY*2)*lD + cMY*cMY - cRadius*cRadius;
  if xX > 1 then
  begin
    X := X / xX;
    C := C / xX;
  end;
  if (X*X/4) < C then
    Exit;
  t := SQRT( X*X/4 - C );;
  Result[0].X := -X/2 + t;
  Result[0].Y := lKX * Result[0].X + lD;
  Result[1].X := -X/2 - t;
  Result[1].Y := lKX * Result[1].X + lD;
end;
Mir war langweilig
Miniaturansicht angehängter Grafiken
s2_144.png   s1_185.png  
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#5

Re: Schnittpunkt Linie vs. Kreis

  Alt 26. Mär 2009, 04:47
Und da es schon angesprochen wurde, hier das ganze noch vektoriell in Pseudocode (um den ganzen Krams zu sparen den man betreiben muss um Vektoroperationen durch Funktionen zu ersetzen). Im Grunde läuft es auf eine pq- bzw. Mitternachtsformel hinaus.

Delphi-Quellcode:
// M : Mittelpunkt des Kreises
// r : Kreisradius
// A : Stützpunkt der zu schneidenden Strecke/Gerade
// V : Richtungsvektor der Strecke/Gerade (Wenn diese aus 2 Punkten A und B gebildet ist, ist dies B-A)
// U : Hilfsvektor
// p, q, d, x1, x2 : Hilfsvariablen (Skalare, keine Vektoren)

  U := A-M;
  p := U*V;
  q := U^2 - r^2;
  d := p^2 - q;

  if d < 0 then
    Kein_Schnittpunkt
  else
  begin
    d := sqrt(d / |V|);
    x1 := -p + d;
    x2 := -p - d;
  end;

  if (x2>x1) and (x1>0) then
    Schnittpunkt := A + x1*V
  else
  if (x1>x2) and (x2>0) then
    Schnittpunkt := A + x2*V
  else
    Kein_Schnittpunkt_Oder_Schnitt_Hinter_A;
Der je kleinere Wert von x1 und x2 gibt den ersten Schnittpunkt von A aus in Richtung V gesehen, die Bedingung >0 stellt sicher dass kein Punkt "hinter" der Blickrichtung "V gestützt auf A" gefunden wird. Liegt dieser in ]0|1[, ist der Schnittpunkt zwischen den Punkten A und B bzw. A und A+V.

Das ganze klappt nun auch für beliebige Dimensionen, man muss lediglich entsprechende Vektortypen und die zugehörigen Operationen nehmen. Ich hab das z.B. in der Form für 3D in einem kleinen Raytracer im Kugel-Primitive eingesetzt.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Dipl Phys Ernst Winter

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

Re: Schnittpunkt Linie vs. Kreis

  Alt 28. Apr 2009, 22:12
Es gibt zwei oder keinen Schnittpunkt.
Tangiert die Linie den Kreis, so zählt man den Schnittpunkt doppelt.
Autor: DP Ernst Winter
  Mit Zitat antworten Zitat
Namenloser

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

Re: Schnittpunkt Linie vs. Kreis

  Alt 28. Apr 2009, 22:38
Es geht hier um eine Strecke, keine Gerade. Der Code gibt immer den ersten Schnittpunkt zurück. Das ganze lässt sich aber sehr einfach für Geraden und mehrere Schnittpunkte anpassen.
  Mit Zitat antworten Zitat
Dipl Phys Ernst Winter

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

Re: Schnittpunkt Linie vs. Kreis

  Alt 29. Apr 2009, 23:12
Da fand sich bei mir in AnwMath ein diesbezügliches Programm.

Delphi-Quellcode:
type
  TPkt = record x, y: extended end;

// Kreis: M0 Mittelpunkt, r: Radius
// Gerade: P0 Punkt auf der Geraden, m: Steigung
// S1, S2: Schnittpunkte
// Der Funktioswert gibt mit 0..2 die Anzahl der Schnittpunkt zurück
function TForm1.Schnittpunkte(M0, P0: TPkt; r, m: extended;
                                                   var S1, S2: TPkt): integer;
var
  n, a, d, p, q: extended;
begin
  n:= P0.y - m*P0.x - M0.y;
  a:= 1 + m*m;
  p:= 2*(n*m - M0.x);
  q:= M0.x*M0.x + n*n -r*r;
  p:= p/a; q:= q/a; d:= p*p/4 - q;
  if d>eps then begin // Diskriminante > 0, zwei Schnittpunkte
    Result:= 2; d:= Sqrt(d); S1.x:= -p/2 - d; S2.x:= -p/2 + d;
    S1.y:= P0.y + m*(S1.x-P0.x); S2.y:= P0.y + m*(S2.x-P0.x) end
  else if d<-eps then Result:= 0 // Diskriminante < 0, kein Schnittpunk
  else begin // Diskriminante = 0, Berührungspunkt
    Result:= 1; S1.x:= -p/2; S1.y:= P0.y + m*(S1.x-P0.x);
    S2.x:= S1.x; S2.y:= S1.y end;
end;
Angehängte Dateien
Dateityp: exe schnittpunkt_gerade_mit_kreis_521.exe (165,2 KB, 26x aufgerufen)
Autor: DP Ernst Winter
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

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

Re: Schnittpunkt Linie vs. Kreis

  Alt 30. Apr 2009, 07:26
Zitat:
// Gerade: P0 Punkt auf der Geraden, m: Steigung
Und wie gibt man damit eine Senkrechte an?
Uwe Raabe
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#10

Re: Schnittpunkt Linie vs. Kreis

  Alt 30. Apr 2009, 07:29
m := 1E99 sollte reichen
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 00:12 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