WaBis

walter.bislins.ch

Schnittfläche zweier Kreise berechnen

Donnerstag, 4. Mai 2017 - 00:19 | Autor: wabis | Themen: Wissen, Geometrie, Mathematik, Programmierung, Interaktiv
Hier leite ich die Formeln zur Berechnung der Schnittfläche zweier Kreise her. Ich zeige wie der Abstand der Kreise numerisch mit dem Newton-Verfahren berechnet werden kann, wenn die Schnittfläche gegeben ist. Im Rechenformular kann man sich Werte ausrechnen lassen. Am Ende wird der Code des Rechenformulars aufgelistet.

Schnittfläche berechnen

Schnittflächen zweier Kreise

Zum Rechenformular

Die Kreisabschnitte AA gelb und BA blau im Bild rechts können mit denselben Formeln separat berechnet werden. Dazu definieren wir einige Parameter wie im Bild unten beschriftet. Dies sind die Radien der beiden Kreise a und b, sowie deren Abstand d.

Im Bild unten sind zur besseren Übersicht jeweils nur die halben Flächen bezeichnet, in den Formeln wird aber mit den ganzen Flächen gerechnet. Die gesuchten Kreisabschnitte AA und BA berechnet man aus den Kreissektoren AS bzw. BS abzüglich der Dreiecke AD bzw. BD. Die gesuchte Schnittfläche S ist dann einfach die Summe der Kreisabschnitte.

Es müssen die drei folgenden Fälle unterschieden werden:

  • Der Abstand der beiden Kreise d ist gösser als die Summe der beiden Radien a und b → die Kreise überlappen sich nicht, deren Schnittfläche ist also S = 0
  • Der Abstand der Kreiszentren d ist kleiner als die Differenz der beiden Radien → der kleinere Kreis liegt vollständig innerhalb des grösseren Kreises, die Schnittfläche ist gleich der Fläche des kleineren Kreises
  • In allen anderen Fällen überlappen sich die beiden Kreise teilweise → Die Schnittfläche S wird nach den folgenden Formeln berechnet. Die Schnittfläche ist immer ein Wert zwischen 0 und der Fläche des kleineren Kreises.

Schema zweier überlappender Kreise mit Beschriftung der Parameter

Für die Berechnungen der Kreisabschnitte müssen eventuell zwei weitere Fälle unterschieden werden: links der Fall bei dem alle Winkel des Dreiecks a-b-d kleiner als 90° sind, rechts der Fall, bei dem einer der Winkel grösser als 90° ist.

Für die Berechnung der Flächen führen wir den Abschnitt x sowie die Dreieckshöhe h ein. Der Abschnitt y ist entspricht dem Abschnitt x für den Kreis B, es ist also y = dx. Für die Parameter gelten die folgenden Beziehungen nach Pythagoras:

(1)
h^2 = a^2 - x^2 \qquad\qquad h^2 = b^2 - y^2 = b^2 - (d - x)^2

Wir können h eliminieren, indem wir die beiden Gleichungen einander gleich setzen, und nach x auflösen:

(2)
a^2 - x^2 = b^2 - d^2 + 2\,d\,x -x^2

Der Term x2 kommt auf beiden Seiten vor und kann daher auf beiden Seiten gestrichen werden. Dann können wir nach x auflösen, das nur noch mit der ersten Potenz vorkommt.

Im Folgenden werden die Formeln für die beiden Kreise einander gegenüber gestellt. Der Abschnitt x für den linken Kreis entspricht dem Abschnitt y für den rechnten Kreis. Alle Flächen des linken Kreises sind mit A bezeichnet, jene des rechten Kreises mit B.

(3)
x = { { a }^2 - { b }^2 + { d }^2 \over 2 \, d }
mit

-a \le x \le a

(4)
y = { { b }^2 - { a }^2 + { d }^2 \over 2 \, d }
mit

-b \le y \le b

Beachte, dass die Werte x bzw. y negativ sein können. Dies müssen wir berücksichtigen, wenn wir die Fläche der Sektoren AS und BS berechnen.

Zur Berechnung der Sektorflächen AS und BS benötigen wir die Sektorwinkel. Diese können wir im Prinzip aus dem arcsin oder dem arccos erhalten. Der arcsin ist hier nicht geeignet, weil er für negative x und y nicht den gewünschten Winkel zwischen π/2 und π liefert. Daher verwenden wir die arccos Funktion:

(5)
A_\mathrm{S} = { a }^2 \, \arccos \left( x / a \right)
ergibt

0 \le A_\mathrm{S} \le a^2 \, \pi

wobei'
A_\mathrm{S} ' =' 'Fläche des Kreissektors des Kreises A
a ' =' 'Radius des Kreises A
x ' =' 'siehe (3)
(6)
B_\mathrm{S} = { b }^2 \, \arccos \left( y / b \right)
ergibt

0 \le B_\mathrm{S} \le b^2 \, \pi

wobei'
B_\mathrm{S} ' =' 'Fläche des Kreissektors des Kreises B
b ' =' 'Radius des Kreises B
y ' =' 'siehe (4)

Beachte, dass die hier berechnete Fläche AS das doppelte der gelb gezeichneten Fläche im obigen Bild ist. Dies gilt auch für die folgenden Berechnungen.

Um die Kreisabschnitte (Kreissegmente) AA und BA zu berechnen, benötigen wir die Flächen der Dreiecke AD und BD. Die Kreisabschnitte erhält man, indem man von den Kreissektoren die Flächen der Dreiecke abzieht, siehe (9) und (10).

Bei negativen x bzw. y wird der entsprechende Sektorwinkel grösser als π und wir müssen die Dreiecksflächen zu den Sektorflächen hinzufügen. In den folgenden Formeln erhalten wir negative Dreiecksflächen für Sektorwinkel grösser als π, sodass diese Fälle in (9) und (10) automatisch korrekt behandelt werden. Wir brauchen also keine extra Fallunterscheidung dafür zu machen.

(7)
A_\mathrm{D} = 2 \cdot { x\,h \over 2 } = x \, \sqrt{ { a }^2 - { x }^2 }
mit

| x | \le | a |

ergibt

-A_{ \mathrm{D}, \mathrm{max} } \le A_\mathrm{D} \le A_{ \mathrm{D}, \mathrm{max} }

wobei'
A_\mathrm{D} ' =' 'Dreicksfläche des Kreissektors von Kreis A
x ' =' 'siehe (3)
a ' =' 'Radius des Kreises A
(8)
B_\mathrm{D} = 2 \cdot { y\,h \over 2 } = y \, \sqrt{ { b }^2 - { y }^2 }
mit

| y | \le | b |

ergibt

-B_{ \mathrm{D}, \mathrm{max} } \le B_\mathrm{D} \le B_{ \mathrm{D}, \mathrm{max} }

wobei'
B_\mathrm{D} ' =' 'Dreicksfläche des Kreissektors von Kreis B
y ' =' 'siehe (4)
b ' =' 'Radius des Kreises B

Die Kreisabschnitts-Flächen sind:

(9)
A_\mathrm{A} = A_\mathrm{S} - A_\mathrm{D}
wobei'
A_\mathrm{A} ' =' 'Kreisabschnitt-Fläche
A_\mathrm{S} ' =' 'Kreissektor-Fläche (5)
A_\mathrm{D} ' =' 'Dreiecks-Fläche des Kreissektors (7)
(10)
B_\mathrm{A} = B_\mathrm{S} - B_\mathrm{D}
wobei'
B_\mathrm{A} ' =' 'Kreisabschnitt-Fläche
B_\mathrm{S} ' =' 'Kreissektor-Fläche (6)
B_\mathrm{D} ' =' 'Dreiecks-Fläche des Kreissektors (8)

Und schliesslich erhalten wir die Schnittfläche S der zwei Kreise:

(11)
S = A_\mathrm{A} + B_\mathrm{A}
wobei'
S ' =' 'Schnittfläche der Kreise
A_\mathrm{A} ' =' 'Kreisabschnittfläche von Kreis A, siehe (9)
B_\mathrm{A} ' =' 'Kreisabschnittfläche von Kreis B, siehe (10)

Abstand berechnen

Wenn wir die Schnittfläche der zwei Kreise kennen, können wir den Abstand der Kreise berechnen. Im Prinzip müsste man dazu einfach die Formel (11) nach Einsetzen aller Zwischenformeln nach d auflösen. Da aber d sowohl im arccos, unter der Wurzel und separat steht, kann die Formel nicht analytisch nach d aufgelöst werden. Wir müssen ein numerisches Verfahren wie das Newton-Verfahren anwenden.

Beim Newton-Verfahren muss man einen sinnvollen Startwert vorgeben. Zudem sollte man die Funktion, deren Nullstelle man sucht, grafisch aufzeichnen, um zu sehen, ob es eine eindeutige Lösung gibt und wo ein geeigneter Startwert angesetzt werden muss, damit das Verfahren immer eine Lösung findet.

Ich generiere deshalb eine Grafik für verschiedene Radien und Abstände, um das Verhalten der Funktion zu analysieren:

In der Grafik ist die Schnittfläche S als Funktion des Abstandes der Kreise d für verschiedene Kombinationen von Kreisradien a und b aufgezeichnet. Wenn man nun zum Beispiel den Abstand d wissen will, bei dem die Schnittfläche 1 ist (rote Linie), so sucht man jene blaue Linie, die den beiden Radien der Kreise entspricht und sucht deren Schnittpunkt mit der roten Linie. Unterhalb des Schnittpunktes kann man den Abstand d ablesen.

Für das Newton-Verfahren ist wichtig, dass die blauen Kurven erstens die rote Linie überhaupt schneiden. Dies gilt nicht für alle Radien, aber die entsprechenden Fälle kann man aussortieren. Zweitens kann man sehen, dass es für jede blaue Linie nur genau einen Schnittpunkt mit der roten Linie gibt. D.h. es gibt immer eine eindeutige Lösung.

Die blauen Linien schneiden die rote Linie meist in einem steilen Winkel und die blauen Linien sind in einem grossen Bereich praktisch gerade. Das sind ideale Voraussetzungen für das Newton-Verfahren. Problematisch werden die Grenzfälle, wo die blauen Linien horizontal in die Horizontale über gehen. In diesen Fällen ist das Newton-Verfahren überfordert, da es bei horizontalen Lininen nicht gut oder überhaupt nicht konvergiert. Dies kann ich korrigieren, indem ich an die Enden je eine Parabel anhänge, welche die Funktion so erweitert, dass sie kontinuierlich abfallend wird. Damit kann das Verfahren zwar Werte ein wenig ausserhalb des Wertebereiches liefern, aber diese können in den Wertebereich zurück gespiegelt werden.

Als Startwert für das Newton-Verfahren kann d = (a+b)/2 gesetzt werden.

Rechenformular

Um die Schnittfläche der beiden Kreise zu berechnen, gib a, b und den Abstand d ein. Die resultierende Schnittfläche wird im Feld S angezeigt.

Um den benötigten Abstand der beiden Kreise für eine vorgegebene Schnittfläche zu berechnen, gib in das Feld S die Schnittfläche ein. Der zugehörige Abstand wird im Feld d angezeigt.

Code

#INCLUDE JsGraph.inc
#INCLUDE ControlPanel.inc
#INCLUDE NewtonSolver.inc

{{col|50}}

<jscript>

function Area( a, b, d ) {
  // Schnittfläche berechnen
  var x = (a*a - b*b + d*d) / (2*d);
  var As = a*a * Math.acos( x / a );
  var Ad = x * Math.sqrt( a*a - x*x );
  var Aa = As - Ad;
  var y = (b*b - a*a + d*d) / (2*d);
  var Bs = b*b * Math.acos( y / b );
  var Bd = y * Math.sqrt( b*b - y*y );
  var Ba = Bs - Bd;
  return Aa + Ba;
}

function S( a, b, d ) {
  // Test ob d ausserhalb des Bereiches liegt
  if (d >= a + b) return 0;
  if (d <= Math.abs(a-b)) {
    var r = (a > b) ? b : a;
    return r*r * Math.PI;
  }
  return Area( a, b, d );
}

function Sx( a, b, d ) {
  // Funktion an den Enden des Wertebereiches d für das Newton-Verfahren erweitern mit Parabeln
  var dmax = a + b;
  if (d >= dmax) return -Math.pow(d-dmax, 2);
  var dmin = Math.abs(a-b);
  if (d <= dmin) {
    var r = (a > b) ? b : a;
    var Smin = r*r * Math.PI;
    return Math.pow(d-dmin,2) + Smin;
  }
  return Area( a, b, d );
}

var Model = {
  a: 1,
  b: 1,
  d: 1.5,
  S: 0,
  S_field: 0,

  Update: function() {
    // ungültige Eingaben korrigieren
    if (isNaN(this.a)) this.a = 1;
    if (isNaN(this.b)) this.b = 1;
    if (isNaN(this.d)) this.d = 1.5;
    if (isNaN(this.S_field)) this.S_field = this.S;
    this.a = Math.abs(this.a);
    this.b = Math.abs(this.b);
    this.d = Math.abs(this.d);
    // test, ob S verändert wurde
    if (this.S != this.S_field) {
      this.S = Math.abs(this.S_field);
      this.d = this.ComputeD();
    } else {
      this.S = S( this.a, this.b, this.d );
    }
    this.S_field = this.S;
  },

  ComputeD: function() {
    // wenn S ausserhalb des Wertebereiches liegt...
    if (this.S <= 0) return this.a + this.b;
    var r = (this.a > this.b) ? this.b : this.a;
    var smax = Math.PI * r * r;
    if (this.S >= smax) {
      this.S = smax;
      return 0;
    }
    // Abstand d mit Newton-Verfahren berechnen
    var me = this;
    var d = SolveWithNewton( 
      function(x){ 
        return Sx( me.a, me.b, x ); 
      }, 
      this.S, (this.a+this.b)/2, 1e-6
    );
    // wenn d ausserhalb des Wertebereiches 0..a+b liegt, dann 
    // d in den Wertebereich zurück spiegeln
    if (d < 0) d = -d;
    if (d > this.a+this.b) d = 2 * (this.a+this.b) - d;
    return d;
  }
}

var ModelGraph = NewGraph2D( {
  Id: 'ModelGraph',
  Width: '100%',
  Height: '75%',
  DrawFunc: DrawModelGraph,
  AutoReset: true,
  AutoClear: true,
  AutoScalePix: true
} );

function DrawModelGraph( g ) {

  // compute window size
  var abd = Model.a + Model.b + Model.d;
  if (Model.a + Model.d < Model.b) abd = 2 * Model.b;
  if (Model.b + Model.d < Model.a) abd = 2 * Model.a;
  var wModel = 1.05 * abd;
  var hModel = (Model.a > Model.b) ? Model.a : Model.b;
  hModel *= 2.1;
  if (wModel == 0 || hModel == 0) return;
  var vpRatio = g.VpInnerWidth / g.VpInnerHeight;
  var modelRatio = wModel / hModel;
  var WinWidth = wModel;
  var WinHeight = hModel;
  if (modelRatio > vpRatio) {
    WinHeight = wModel / vpRatio;
  } else {
    WinWidth = hModel * vpRatio;
  }
  var l = Model.a;
  if (Model.b - Model.d > Model.a) l = Model.b - Model.d;
  var WinXmin = -(WinWidth/2 - abd/2 + l);
  var WinYmin = -0.5 * WinHeight;

  g.SetWindowWH( WinXmin, WinYmin, WinWidth, WinHeight );

  // draw circles
  g.SetAlpha( 0.5 );
  g.SetAreaAttr( '#f88', 'black', 2 );
  g.Circle( 0, 0, Model.a, 3 );
  g.SetAreaAttr( '#88f', 'black', 2 );
  g.Circle( Model.d, 0, Model.b, 3 );

  g.SetAlpha( 1 );
  g.Circle( 0, 0, Model.a, 1 );
  g.Circle( Model.d, 0, Model.b, 1 );

  // draw circle centers
  g.SetMarkerAttr( 'Plus', 12, 'black', 'black', 1 );
  g.Marker( 0, 0 );
  g.Marker( Model.d, 0 );

  // draw a, b, d
  var rx = Math.sin(Math.PI/4);
  var ry = Math.cos(Math.PI/4);
  g.SetMarkerAttr( 'Arrow1', 10 );
  g.SetAreaAttr( 'red', 'red', 2 );
  g.Arrow( 0, 0, -Model.a*rx, Model.a*ry );
  g.SetTextSize( 24 );
  g.SetTextColor( 'red' );
  g.SetTextAlign( 'left', 'bottom' );
  g.SetTextPadding( 5 );
  g.Text( 'a', -Model.a*rx/2, Model.a*ry/2 );

  g.SetAreaAttr( 'blue', 'blue', 2 );
  g.Arrow( Model.d, 0, Model.b*rx+Model.d, Model.b*ry );
  g.SetTextColor( 'blue' );
  g.SetTextAlign( 'right', 'bottom' );
  g.Text( 'b', Model.d+Model.b*rx/2, Model.b*ry/2 );

  g.SetLineAttr( 'black', 2 );
  g.Line( 0, 0, Model.d, 0 );
  g.SetTextAlign( 'center', 'bottom' );
  g.SetTextColor( 'black' );
  g.Text( 'd', Model.d/2, 0 );
}

</jscript>

{{col}}

<jscript>

ControlPanels.NewPanel( {
    ModelRef: 'Model',
    NCols: 2,
    PanelFormat: 'InputMaxWidth',
    OnModelChange: UpdateAll,
    Format: 'std',
    Digits: 6,
  }

).AddHeader( { 
    ColSpan: 4,
    Text: ControlPanels.ResetButtonR(),
  }

).AddTextField( {
    Name: 'a'
  }

).AddTextField( {
    Name: 'b'
  }

).AddTextField( {
    Name: 'd',
  }

).AddTextField( {
    Name: 'S',
    ValueRef: 'S_field'
  }

).Render();


function UpdateAll() {
  Model.Update();
  ControlPanels.Update();
  ModelGraph.Redraw();
}

function Reset() {
  ControlPanels.Reset();
  Model.S = Model.S_field;
  UpdateAll();
}

xOnLoad( UpdateAll );

</jscript>


Dein Kommentar zu diesem Artikel
Name
Email optional; wird nicht angezeigt
Kommentar
  • Name wird bei deinem Kommentar angezeigt.
  • Email ist nur für den Administrator, sie wird nicht angezeigt.
  • Du kannst deine Kommentare eine Zeit lang editieren oder löschen.
  • Du kannst Formatierungen im Kommentar verwenden, z.B: Code, Formeln, usw.
  • Externen Links und Bilder werden nicht angezeigt, bis sie der Admin freischaltet.
Weitere Infos zur Seite
Erzeugt Donnerstag, 4. Mai 2017
von wabis
Zum Seitenanfang
Geändert Donnerstag, 11. Mai 2017
von wabis